/// <summary> /// Evals the specified lisp code. /// An exception may occure if the lisp code is invalid. /// </summary> /// <param name="lispCode">The lisp code.</param> /// <param name="scope">The scope.</param> /// <param name="moduleName">The module name and path.</param> /// <param name="tracing">if set to <c>true</c> [tracing].</param> /// <param name="onlyMacroExpand">if set to <c>true</c> [macro expanding].</param> /// <param name="nativeItems">The dictionary with native items.</param> /// <returns>The result of the script evaluation</returns> public static LispVariant Eval(string lispCode, LispScope scope = null, string moduleName = null, bool tracing = false, bool onlyMacroExpand = false, Dictionary <string, object> nativeItems = null) { // first create global scope, needed for macro expanding var currentScope = scope ?? LispEnvironment.CreateDefaultScope(); currentScope.ModuleName = moduleName; currentScope.Tracing = tracing; RegisterNativeObjects(nativeItems, currentScope); int offset; string code = LispUtils.DecorateWithBlock(lispCode, out offset); var ast = LispParser.Parse(code, offset, currentScope); #if ENABLE_COMPILE_TIME_MACROS var expandedAst = LispInterpreter.ExpandMacros(ast, currentScope); #else var expandedAst = ast; #endif LispVariant result = null; if (onlyMacroExpand) { result = new LispVariant(expandedAst); } else { result = LispInterpreter.EvalAst(expandedAst, currentScope); } return(result); }
/// <summary> /// Compiles the specified lisp code into C# code. /// </summary> /// <param name="code">The lisp code.</param> /// <returns>The C# code packed into a LispVariant</returns> public /*static*/ LispVariant CompileToCsCode(string code) { var globalScope = LispEnvironment.CreateDefaultScope(); int offset; code = LispUtils.DecorateWithBlock(code, out offset); var ast = LispParser.Parse(code, offset, globalScope); //var expandedAst = ExpandMacros(ast, globalScope); var compileResult = Compile(ast, globalScope, " ", "__return__", "scope"); var csCode = "namespace CsLisp\n{\nusing System;\nclass CompiledLisp\n{\n // functions:\n" + ShiftLines(compileResult.Item2, " ") + "\n public static LispVariant LispMain(string[] args)\n {\n var scope = new LispScope();\n LispVariant __return__;\n\n" + ShiftLines(compileResult.Item1, " ") + " return __return__;\n }\n\n public static void Main(string[] args)\n {\n var startTickCount = Environment.TickCount;\n LispMain(args);\n Console.WriteLine(string.Format(\"Execution time = {0} s\", (Environment.TickCount - startTickCount)*0.001));\n }\n}\n}"; return(new LispVariant(csCode)); }
/// <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); }