private bool HitsBreakpoint(int lineNo, string moduleName, LispScope scope) { foreach (var breakpoint in Breakpoints) { bool isSameModule = IsSameModule(breakpoint.ModuleName, scope != null ? scope.ModuleName : moduleName); if (isSameModule && (lineNo == breakpoint.LineNo)) { if (breakpoint.Condition.Length > 0 && scope != null) { try { LispVariant result = Lisp.Eval(breakpoint.Condition, scope, scope.ModuleName); return(result.BoolValue); } catch { Output.WriteLine("Error: bad condition for line {0}: {1}", breakpoint.LineNo, breakpoint.Condition); return(false); } } return(true); } } return(false); }
/// <summary> /// See interface. /// </summary> public LispVariant DebuggerLoop(string script, string moduleName, bool tracing = false) { LispVariant result = null; var bRestart = true; while (bRestart) { // save the source code if the script is transfered via command line if (moduleName == LispUtils.CommandLineModule) { CommandLineScript = script; } var globalScope = LispEnvironment.CreateDefaultScope(); globalScope.Input = Input; globalScope.Output = Output; globalScope.Debugger = this; try { result = Lisp.Eval(script, globalScope, moduleName, tracing: tracing); Reset(); } catch (LispStopDebuggerException) { bRestart = false; } catch (Exception exception) { Output.WriteLine("\nException: {0}", exception); string stackInfo = exception.Data.Contains(LispUtils.StackInfo) ? (string)exception.Data[LispUtils.StackInfo] : string.Empty; Output.WriteLine("\nStack:\n{0}", stackInfo); bRestart = InteractiveLoop(this, globalScope, startedFromMain: true); } if (bRestart) { Output.WriteLine("restart program"); // process empty script --> just start interactive loop if (result == null) { bRestart = InteractiveLoop(this, globalScope, startedFromMain: true); } } globalScope.Debugger = null; } return(result); }
/// <summary> /// Processing of the interactive loop of the debugger. /// </summary> /// <param name="debugger">The debugger.</param> /// <param name="initialTopScope">The initial top scope.</param> /// <param name="startedFromMain">if set to <c>true</c> [started from main].</param> /// <param name="tracing">if set to <c>true</c> tracing is enabled.</param> /// <returns>True if program should be restarted.</returns> /// <exception cref="LispStopDebuggerException"></exception> /// <exception cref="CsLisp.LispStopDebuggerException"></exception> public static bool InteractiveLoop(LispDebugger debugger = null, LispScope initialTopScope = null, bool startedFromMain = false, bool tracing = false) { string interactiveScript = string.Empty; startedFromMain = startedFromMain || debugger == null; if (debugger == null) { debugger = new LispDebugger(); } var globalScope = initialTopScope != null ? initialTopScope.GlobalScope : LispEnvironment.CreateDefaultScope(); // do not switch off tracing if already enabled if (!globalScope.Tracing) { globalScope.Tracing = tracing; } var topScope = initialTopScope != null ? initialTopScope : globalScope; var currentScope = topScope; var bContinueWithNextStatement = false; var bRestart = false; do { debugger.Output.Write(debugger != null ? DbgPrompt : Prompt); // Warning: // QProcess and .NET >3.5 does not work correclty reading from input !!! // see: http://www.qtcentre.org/threads/62415-QProcess-not-communicating-with-net-framework-gt-3-5 // ==> CsLisp is now using .NET 3.5 ! var cmd = debugger.Input.ReadLine(); cmd = cmd != null?cmd.Trim() : null; if (cmd == null || cmd.Equals("exit") || cmd.Equals("quit") || cmd.Equals("q")) { bContinueWithNextStatement = true; bRestart = false; if (!startedFromMain) { throw new LispStopDebuggerException(); } } else if (cmd.Equals("help") || cmd.Equals("h")) { ShowInteractiveCmds(debugger.Output); } else if (cmd.Equals("about")) { LispUtils.ShowAbout(debugger.Output); } else if (cmd.Equals("funcs")) { globalScope.DumpFunctions(); } else if (cmd.Equals("macros")) { globalScope.DumpMacros(); } else if (cmd.Equals("builtins")) { globalScope.DumpBuiltinFunctions(); } else if (cmd.StartsWith("doc")) { var items = cmd.Split(' '); if (items.Length > 1) { string docCmd = "(doc '" + items[1] + ")"; LispVariant result = Lisp.Eval(docCmd, currentScope, currentScope.ModuleName); debugger.Output.WriteLine("{0}", result); } else { globalScope.DumpBuiltinFunctionsHelp(); } } else if (cmd.StartsWith("searchdoc")) { var items = cmd.Split(' '); if (items.Length > 1) { string docCmd = "(searchdoc '" + items[1] + ")"; LispVariant result = Lisp.Eval(docCmd, currentScope, currentScope.ModuleName); debugger.Output.WriteLine("{0}", result); } else { globalScope.DumpBuiltinFunctionsHelp(); } } else if (cmd.Equals("modules")) { globalScope.DumpModules(); } else if (cmd.StartsWith("clear")) { ClearBreakpoints(debugger, cmd); } else if (cmd.Equals("stack") || cmd.StartsWith("k")) { topScope.DumpStack(currentScope.GetCallStackSize()); } else if (cmd.Equals("code") || cmd.StartsWith("c")) { var script = string.Empty; var moduleName = currentScope.ModuleName; if (moduleName == null) { script = interactiveScript; } else { script = moduleName.StartsWith(LispEnvironment.EvalStrTag) ? moduleName.Substring(LispEnvironment.EvalStrTag.Length + moduleName.IndexOf(":", LispEnvironment.EvalStrTag.Length)) : LispUtils.ReadFileOrEmptyString(moduleName); } // use the script given on command line if no valid module name was set if (string.IsNullOrEmpty(script)) { script = debugger.CommandLineScript; } ShowSourceCode(debugger, script, currentScope.ModuleName, currentScope.CurrentLineNo); } else if (cmd.StartsWith("list") || cmd.StartsWith("t")) { debugger.ShowBreakpoints(); } else if (cmd.StartsWith("break ") || cmd.StartsWith("b ")) { AddBreakpoint(debugger, cmd, currentScope.ModuleName); } else if (cmd.Equals("up") || cmd.StartsWith("u")) { if (currentScope.Next != null) { currentScope = currentScope.Next; } } else if (cmd.Equals("down") || cmd.StartsWith("d")) { if (currentScope.Previous != null) { currentScope = currentScope.Previous; } } else if (cmd.Equals("step") || cmd.Equals("s")) { debugger.DoStep(currentScope); bContinueWithNextStatement = true; } else if (cmd.Equals("over") || cmd.Equals("v")) { debugger.DoStepOver(currentScope); bContinueWithNextStatement = true; } else if (cmd.Equals("out") || cmd.Equals("o")) { debugger.DoStepOut(currentScope); bContinueWithNextStatement = true; } else if (cmd.Equals("run") || cmd.Equals("r")) { debugger.DoRun(); bContinueWithNextStatement = true; } else if (cmd.Equals("locals") || cmd.StartsWith("l")) { currentScope.DumpVars(); } else if (cmd.Equals("globals") || cmd.StartsWith("g")) { globalScope.DumpVars(); } else if (cmd.Equals("restart")) { bContinueWithNextStatement = true; bRestart = true; } else if (cmd.Equals("version") || cmd.Equals("ver")) { LispUtils.ShowVersion(debugger.Output); } else { try { LispVariant result = Lisp.Eval(cmd, currentScope, currentScope.ModuleName); debugger.Output.WriteLine("result={0}", result); interactiveScript += cmd + '\n'; } catch (Exception ex) { debugger.Output.WriteLine("Exception: " + ex.Message); } } } while (!bContinueWithNextStatement); return(bRestart); }