Beispiel #1
0
        private void DoStepOut(LispScope currentScope)
        {
            var currentCallStackSize = currentScope.GetCallStackSize();

            IsStopStepFcn = (scope) => currentCallStackSize - 1 >= scope.GetCallStackSize();
            IsProgramStop = true;
        }
Beispiel #2
0
        private void DoStepOver(LispScope currentScope)
        {
            var currentCallStackSize = currentScope.GetCallStackSize();

            IsStopStepFcn = (scope) => (currentCallStackSize >= scope.GetCallStackSize()) && !scope.IsInEval;
            IsProgramStop = true;
        }
Beispiel #3
0
        /// <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);
        }
Beispiel #4
0
 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);
 }
Beispiel #5
0
        private static string ResolveFunction(object astItem, LispScope globalScope)
        {
            LispFunctionWrapper fw = ((LispVariant)globalScope[astItem.ToString()]).FunctionValue;
            Func <object[], LispScope, LispVariant> func = fw.Function;
            MethodInfo method = func.Method;

            return(method.Name);
        }
Beispiel #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="LispException"/> class.
 /// </summary>
 /// <param name="text">The text.</param>
 /// <param name="scope">The scope.</param>
 public LispException(string text, LispScope scope = null)
     : base(text)
 {
     if (scope != null)
     {
         this.AddModuleNameAndStackInfos(scope.ModuleName, scope.DumpStackToString());
         this.AddTokenInfos(scope.CurrentToken);
     }
 }
Beispiel #7
0
 /// <summary>
 /// See interface.
 /// </summary>
 public bool NeedsBreak(LispScope scope, LispBreakpointPosition posInfosOfCurrentAstItem)
 {
     if ((IsProgramStop && IsStopStepFcn(scope)) || HitsBreakpoint(posInfosOfCurrentAstItem.Item3, scope.ModuleName, scope))
     {
         IsProgramStop = false;
         return(true);
     }
     return(false);
 }
Beispiel #8
0
        private static Tuple <string, string> Compile(object ast, LispScope globalScope, string shift, string saveReturn, string scopeName)
        {
            if (ast is IEnumerable <object> )
            {
                return(Compile((IEnumerable <object>)ast, globalScope, string.Empty, saveReturn, scopeName));
            }
            var value = ast as LispVariant;
            var temp  = value != null?value.ToStringCompiler() : ast.ToString();

            return(new Tuple <string, string>(temp, string.Empty));
        }
Beispiel #9
0
        public int GetCallStackSize()
        {
            LispScope current = this;
            int       i       = 0;

            do
            {
                current = current.Previous;
                i++;
            } while (current != null);
            return(i);
        }
Beispiel #10
0
        public static object ExpandMacros(object ast, LispScope globalScope)
        {
            object result = ast;
            bool   anyMacroReplaced;

            do
            {
                anyMacroReplaced = false;
                result           = ExpandMacros(result, globalScope, ref anyMacroReplaced);
            } while (anyMacroReplaced);
            return(result);
        }
Beispiel #11
0
 /// <summary>
 /// Gets the additional arguments from the scope.
 /// </summary>
 /// <param name="scope">The scope.</param>
 /// <returns>The result.</returns>
 public static object[] GetAdditionalArgs(this LispScope scope)
 {
     if (scope.ContainsKey(LispEnvironment.ArgsMeta))
     {
         LispVariant variant = scope[LispEnvironment.ArgsMeta] as LispVariant;
         if (variant != null)
         {
             return(variant.ListValue.ToArray());
         }
     }
     return(new object[0]);
 }
Beispiel #12
0
 /// <summary>
 /// Initializes a new instance of the <see cref="LispScope"/> class.
 /// </summary>
 /// <param name="fcnName">Name of the FCN.</param>
 /// <param name="globalScope">The global scope.</param>
 /// <param name="moduleName">The current module name for the scope.</param>
 public LispScope(string fcnName, LispScope globalScope = null, string moduleName = null)
 {
     Name        = fcnName;
     GlobalScope = globalScope ?? this;
     ModuleName  = moduleName;
     if (ModuleName == null && globalScope != null)
     {
         ModuleName = globalScope.ModuleName;
     }
     CurrentToken = null;
     Input        = Console.In;
     Output       = Console.Out;
 }
Beispiel #13
0
        /// <summary>
        /// See interface.
        /// </summary>
        public void InteractiveLoop(LispScope initialTopScope, IList <object> currentAst = null, bool startedFromMain = false, bool tracing = false)
        {
            if (currentAst != null)
            {
                var lineNumber = initialTopScope != null ? initialTopScope.CurrentLineNo : -1;
                var startPos   = initialTopScope != null ? initialTopScope.CurrentToken.StartPos : -1;
                var stopPos    = initialTopScope != null ? initialTopScope.CurrentToken.StopPos : -1;
                var moduleName = initialTopScope != null ? initialTopScope.ModuleName : "?";
                var tokenTxt   = initialTopScope != null?initialTopScope.CurrentToken.ToString() : "?";

                Output.WriteLine("--> " + currentAst[0] + " line=" + lineNumber + " start=" + startPos + " stop=" + stopPos + " module=" + moduleName + " token=" + tokenTxt);
            }
            InteractiveLoop(this, initialTopScope, startedFromMain, tracing);
        }
Beispiel #14
0
        public string DumpStackToString(int currentLevel = -1)
        {
            string    ret     = string.Empty;
            LispScope current = this;
            int       i       = GetCallStackSize();

            do
            {
                string currentItem = currentLevel == i ? "-->" : "   ";

                ret     = string.Format("{0,3}{1,5} name={2,-35} lineno={3,-4} module={4}\n", currentItem, i, current.Name, current.CurrentLineNo, current.ModuleName) + ret;
                current = current.Previous;
                i--;
            } while (current != null);
            return(ret);
        }
Beispiel #15
0
        /// <summary>
        /// Determines whether the given name is available in the closure chain.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="closureScopeFound">The closure scope found.</param>
        /// <param name="value">The found value.</param>
        /// <returns>True if name was found.</returns>
        private bool IsInClosureChain(string name, out LispScope closureScopeFound, out object value)
        {
            if (ClosureChain != null)
            {
                if (ClosureChain.TryGetValue(name, out value))
                {
                    closureScopeFound = ClosureChain;
                    return(true);
                }
                return(ClosureChain.IsInClosureChain(name, out closureScopeFound, out value));
            }

            closureScopeFound = null;
            value             = null;
            return(false);
        }
Beispiel #16
0
        /// <summary>
        /// Parses the specified code.
        /// string ==&gt; List(Tokens) ==&gt; List(object) mit object == List(object), LispVariant(string, int, double, and ==&gt; for unquoting Symbols)
        /// </summary>
        /// <param name="code">The code.</param>
        /// <param name="offset">The position offset.</param>
        /// <param name="scope">The scope.</param>
        /// <returns>Abstract syntax tree as container</returns>
        public static object Parse(string code, int offset = 0, LispScope scope = null)
        {
            object parseResult = null;
            string moduleName  = string.Empty;

            // set tokens at LispScope to improve debugging and
            // support displaying of error position
            var tokens = LispTokenizer.Tokenize(code, offset).ToList();

            if (scope != null)
            {
                scope.Tokens = tokens;
                moduleName   = scope.ModuleName;
            }

            ParseTokens(moduleName, tokens, 0, ref parseResult, isToplevel: true);

            return(parseResult);
        }
Beispiel #17
0
        /// <summary>
        /// Resolves the items of the ast in the given scope.
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="astAsList"></param>
        /// <param name="compile"></param>
        /// <returns></returns>
        public static List <object> ResolveArgsInScopes(LispScope scope, IEnumerable <object> astAsList, bool compile)
        {
            var  astWithResolvedValues = new List <object>();
            var  firstElement          = astAsList.FirstOrDefault();
            bool?isSpecialForm         = null;

            foreach (var elem in astAsList)
            {
                object resolvedElem;
                if ((isSpecialForm != null && (bool)isSpecialForm) || !IsSymbol(elem))
                {
                    resolvedElem = elem;
                }
                else
                {
                    resolvedElem = scope.ResolveInScopes(elem, elem == firstElement);
                }
                astWithResolvedValues.Add(resolvedElem);

                if (isSpecialForm == null)
                {
                    var    firstElem = new LispFunctionWrapper();
                    object first     = null;
                    try
                    {
                        first     = astWithResolvedValues.First();
                        firstElem = ((LispVariant)first).FunctionValue;
                    }
                    catch (LispException)
                    {
                        if (!compile)
                        {
                            throw new LispException("Function \"" + first + "\" not found", scope);
                        }
                    }
                    isSpecialForm = firstElem.IsSpecialForm;
                }
            }
            return(astWithResolvedValues);
        }
Beispiel #18
0
        private static IEnumerable <object> ReplaceFormalArgumentsInExpression(IEnumerable <object> formalArguments, IList <object> astAsList, IEnumerable <object> expression, LispScope scope, ref bool anyMacroReplaced)
        {
            // replace (quoted-macro-args) --> '(<real_args>)
            int  i        = 1;
            bool replaced = false;
            IEnumerable <object> realArguments       = astAsList.Skip(1).ToList();
            List <object>        quotedRealArguments = new List <object>()
            {
                new LispVariant(LispType.Symbol, LispEnvironment.Quote), realArguments
            };

            expression = ReplaceSymbolWithValueInExpression(new LispVariant(LispType.Symbol, "quoted-macro-args"), quotedRealArguments, expression, true, ref replaced);

            foreach (var formalArgument in formalArguments)
            {
                object value;
                if (astAsList[i] is IEnumerable <object> )
                {
                    value = ExpandMacros(astAsList[i], scope, ref anyMacroReplaced);
                    if (value is LispVariant)
                    {
                        var vairantValue = value as LispVariant;
                        if (vairantValue.IsList)
                        {
                            value = vairantValue.ListValue;
                        }
                    }
                }
                else
                {
                    value = new LispVariant(astAsList[i]);
                }
                expression = ReplaceSymbolWithValueInExpression((LispVariant)formalArgument, value, expression, false, ref anyMacroReplaced);
                i++;
            }
            return(expression);
        }
Beispiel #19
0
        private static object ExpandMacros(object ast, LispScope globalScope, ref bool anyMacroReplaced)
        {
            if (ast == null || ast is LispVariant)
            {
                return(ast);
            }

            var astAsList = ((IEnumerable <object>)ast).ToList();

            if (astAsList.Count == 0)
            {
                return(ast);
            }

            // compile time macro: process define-macro statements ==> call special form, this will add macro to global scope as side effect
            var function     = astAsList.First();
            var functionName = function.ToString();

            if (globalScope != null && globalScope.ContainsKey(functionName))
            {
                var fcn = ((LispVariant)globalScope[functionName]).FunctionValue;
                if (fcn.IsEvalInExpand)
                {
                    var args = new List <object>(astAsList);
                    args.RemoveAt(0);

                    // process compile time macro definition
                    //   --> side effect: add macro definition to internal macro scope
                    fcn.Function(args.ToArray(), globalScope);

                    // compile time macros definitions will be removed from code in expand macro phase
                    // because only the side effect above is needed for further macro replacements
                    return(null);
                }
            }

            // compile time macros: process macro expansion in an expression which calls a macro
            if (LispEnvironment.IsMacro(function, globalScope))
            {
                var macro = LispEnvironment.GetMacro(function, globalScope);
                if (macro is LispMacroCompileTimeExpand)
                {
                    anyMacroReplaced = true;
                    var macroExpand = (LispMacroCompileTimeExpand)macro;
                    var astWithReplacedArguments = ReplaceFormalArgumentsInExpression(macroExpand.FormalArguments, astAsList, macroExpand.Expression, globalScope, ref anyMacroReplaced).ToList();   // PATCH
                    // process recursive macro expands (do not wrap list as LispVariant at this point)
                    return(ConvertLispVariantListToListIfNeeded(EvalAst(astWithReplacedArguments, globalScope)));
                }
            }

            var expandedAst = new List <object>();

            // Expand recursively and handle enumarations (make them flat !)
            foreach (var elem in astAsList)
            {
                var expandResult = ExpandMacros(elem, globalScope);
                // ignore code which is removed in macro expand phase
                if (expandResult != null)
                {
                    // process recursive macro expands (do not wrap list as LispVariant at this point)
                    expandedAst.Add(ConvertLispVariantListToListIfNeeded(expandResult));
                }
            }

            return(expandedAst);
        }
Beispiel #20
0
 private static void RegisterNativeObjects(Dictionary <string, object> nativeItems, LispScope currentScope)
 {
     if (nativeItems != null)
     {
         foreach (KeyValuePair <string, object> item in nativeItems)
         {
             currentScope[item.Key] = new LispVariant(LispType.NativeObject, item.Value);
         }
     }
 }
Beispiel #21
0
 public void PushNextScope(LispScope nextScope)
 {
     Next = nextScope;
     nextScope.Previous = this;
 }
Beispiel #22
0
        private static Tuple <string, string> Compile(IEnumerable <object> ast, LispScope globalScope, string shift, string saveReturn, string scopeName)
        {
            string code      = string.Empty;
            string functions = string.Empty;

            var astWithResolvedValues = LispInterpreter.ResolveArgsInScopes(globalScope, ast, true);

            // do --> sequence, d. h. ignorieren
            // defn --> funktion deklarieren
            // def --> variable deklarieren ==> LispVariant a = value;
            // quote
            // setf --> variable zuweisen
            // while
            // lambda
            // if
            // weitere special forms speziell behandeln...
            // --> and, or, apply, quasiquote, definemacro
            object first          = null;
            string args           = string.Empty;
            string separator      = ", ";
            string closeStatement = "";

            for (int i = 0; i < astWithResolvedValues.Count; i++)
            {
                var elem = astWithResolvedValues[i];
                if (first == null)
                {
                    first = elem;
                    var func = (LispVariant)first;
                    if (func.IsSymbol)
                    {
                        // process normal function call
                        string cast = GetFunctionCast(astWithResolvedValues.Count - i - 1);
                        code          += shift + "/*local_func*/((" + cast + ")" + ast.First() + ")(";
                        separator      = ", ";
                        closeStatement = ", " + scopeName + ")";
                    }
                    else
                    {
                        LispFunctionWrapper function = ((LispVariant)first).FunctionValue;
                        if (function.Function == LispEnvironment.def_form)
                        {
                            var compileResult = Compile(astWithResolvedValues[i + 2], globalScope, string.Empty, null, scopeName);
// TODO --> ggf. nur einfache datentypen dekorieren !? siehe bei arg
                            code          += shift + "/*def_form*/LispVariant " + astWithResolvedValues[i + 1] + " = new LispVariant( (object)" + compileResult.Item1 + ")";
                            functions     += compileResult.Item2;
                            separator      = "";
                            closeStatement = "";
                            i += 2;
                        }
                        else if (function.Function == LispEnvironment.defn_form)
                        {
                            // process normal function call
                            functions += shift + "/*defn*/private static LispVariant " + astWithResolvedValues[i + 1] + "(";
                            var argStrg = string.Empty;
                            foreach (var arg in (IEnumerable <object>)astWithResolvedValues[i + 2])
                            {
                                if (argStrg.Length > 0)
                                {
                                    argStrg += ", ";
                                }
                                argStrg += "LispVariant " + arg;
                            }
                            functions     += argStrg + ", LispScope " + scopeName + ")\n";
                            functions     += shift + "{\n";
                            functions     += shift + "LispVariant __return__;\n";
                            functions     += Compile(astWithResolvedValues[i + 3], globalScope, string.Empty, "__return__", scopeName).Item1;
                            functions     += shift + ";\n";
                            functions     += shift + "\nreturn __return__;\n";
                            functions     += shift + "}\n";
                            separator      = "";
                            closeStatement = "";
                            i += 3;
                        }
                        else if (function.Function == LispEnvironment.quote_form)
                        {
                            // (quote (1 2 3)) --> new object[] { 1, 2, 3 }
                            // (quote 'something) --> new LispVariant(LispType.Symbol, "something")
                            code += "/*quote*/new object[] { ";
                            var temp = string.Empty;
                            if (astWithResolvedValues[i + 1] is IEnumerable <object> )
                            {
                                var aList = (IEnumerable <object>)astWithResolvedValues[i + 1];
                                foreach (var item in aList)
                                {
                                    if (temp.Length > 0)
                                    {
                                        temp += ", ";
                                    }
                                    temp += "new LispVariant( ";
                                    temp += Compile(item, globalScope, string.Empty, null, scopeName).Item1;
                                    temp += " )";
                                }
                            }
                            else
                            {
                                LispVariant variant = (LispVariant)astWithResolvedValues[i + 1];
                                temp += "new LispVariant( LispType.Symbol, \"";
                                temp += variant.ToString();
                                temp += "\" )";
                            }
                            code += temp + " }";
                            i++;
                        }
                        else if (function.Function == LispEnvironment.quasiquote_form)
                        {
                            // (quasiquote (1 2 3 ,a)) --> new object[] { 1, 2, 3, 42 }
// TODO korrekt implementieren !!!
                            code += "/*quasiquote*/new object[] { ";
                            var aList = (IEnumerable <object>)astWithResolvedValues[i + 1];
                            var temp  = string.Empty;
                            foreach (var item in aList)
                            {
                                if (temp.Length > 0)
                                {
                                    temp += ", ";
                                }
                                temp += "new LispVariant( ";
                                temp += Compile(item, globalScope, string.Empty, null, scopeName).Item1;
                                temp += " )";
                            }
                            code += temp + " }";
                            i++;
                        }
                        else if (function.Function == LispEnvironment.do_form)
                        {
                            // process do_form
                            separator      = "\n";
                            closeStatement = "";
                            int    j;
                            string temp = "{ /*do*/\n";
                            for (j = i + 1; j < astWithResolvedValues.Count; j++)
                            {
                                var compileResult = Compile(astWithResolvedValues[j], globalScope, shift, saveReturn, scopeName);
                                functions += compileResult.Item2;
                                temp      += compileResult.Item1;
                                if (temp.Length > 0)
                                {
                                    temp += ";\n";
                                }
                            }
                            i     = j;
                            code += temp + "/*do*/ }\n";
                        }
                        else if (function.Function == LispEnvironment.if_form)
                        {
                            code += "if( ";
                            code += Compile(astWithResolvedValues[i + 1], globalScope, string.Empty, null, scopeName).Item1;
                            code += ".ToBool() )\n{\n";
                            code += Compile(astWithResolvedValues[i + 2], globalScope, "    ", null, scopeName).Item1;
                            code += ";\n}\n";
                            if (astWithResolvedValues.Count > i + 3)
                            {
                                code += "else\n{\n";
                                code += Compile(astWithResolvedValues[i + 3], globalScope, "    ", null, scopeName).Item1;
                                code += ";\n}\n";
                                i    += 3;
                            }
                            else
                            {
                                i += 2;
                            }
                        }
                        else if (function.Function == LispEnvironment.while_form)
                        {
                            code += "while( ";
                            code += Compile(astWithResolvedValues[i + 1], globalScope, string.Empty, null, scopeName).Item1;
                            code += ".ToBool() )\n{\n";
                            code += Compile(astWithResolvedValues[i + 2], globalScope, "    ", null, scopeName).Item1;
                            code += ";}\n";
                            i    += 2;
                        }
                        else if (function.Function == LispEnvironment.setf_form)
                        {
                            code += Compile(astWithResolvedValues[i + 1], globalScope, string.Empty, null, scopeName).Item1;
                            code += " = new LispVariant(";
                            code += Compile(astWithResolvedValues[i + 2], globalScope, string.Empty, null, scopeName).Item1;
                            code += ")";
                            i    += 2;
                        }
                        else if (function.Function == LispEnvironment.fn_form)
                        {
                            code += "/*fn*/new LispVariant( LispType.Function, new LispFunctionWrapper( (";
                            var argNames = (IEnumerable <object>)astWithResolvedValues[i + 1];
                            var temp     = string.Empty;
                            foreach (var name in argNames)
                            {
                                if (temp.Length > 0)
                                {
                                    temp += ", ";
                                }
                                temp += "LispVariant " + name;
                            }
                            code += temp;
                            code += ", LispScope _scope) => { LispVariant __ret__; ";
                            code += Compile(astWithResolvedValues[i + 2], globalScope, string.Empty, "__ret__", "_scope").Item1;
                            code += "; return __ret__; }, /*signature*/string.Empty, /*documentation*/string.Empty, false ) )";
                            i    += 2;
                        }
                        else
                        {
                            // process normal function call
                            code += shift;
                            if (!string.IsNullOrEmpty(saveReturn))
                            {
                                code += saveReturn + " = ";
                            }
                            code += "/*func*/LispEnvironment." + ResolveFunction(ast.First(), globalScope) +
                                    "( new object[] { ";
                            separator      = ", ";
                            closeStatement = " }, " + scopeName + ")";
                        }
                    }
                }
                else
                {
                    if (args.Length > 0)
                    {
                        args += separator;
                    }
                    if (elem is IEnumerable <object> )
                    {
                        var compileResult = Compile((IEnumerable <object>)elem, globalScope, shift, saveReturn, scopeName);
                        args      += compileResult.Item1;
                        functions += compileResult.Item2;
                    }
                    else
                    {
                        // decorate simple data types with LispVariant
                        var temp     = (LispVariant)elem;
                        var elemType = temp.Type;
                        if (elemType == LispType.Bool ||
                            elemType == LispType.Int ||
                            elemType == LispType.Double ||
                            elemType == LispType.String)
                        {
                            args += "/*arg*/new LispVariant( (object)" + temp.ToStringCompiler() + " )";
                        }
                        else
                        {
                            args += "/*arg*/" + elem;
                        }
                    }
                }
            }
            code += args + closeStatement;

            return(new Tuple <string, string>(code, functions));
        }
Beispiel #23
0
        /// <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);
        }
Beispiel #24
0
        /// <summary>
        /// Evaluates the given ast.
        /// </summary>
        /// <param name="ast">The ast.</param>
        /// <param name="scope">The scope.</param>
        /// <returns>The result of ast evaluation.</returns>
        /// <exception cref="System.Exception">Unexpected macro modus!</exception>
        public static LispVariant EvalAst(object ast, LispScope scope)
        {
            if (ast == null)
            {
                return(null);
            }

            IList <object> astAsList;

            if (ast is LispVariant)
            {
                var item = (LispVariant)ast;
                // evaluate the value for the symbol
                if (item.IsSymbol)
                {
                    item = new LispVariant(scope.ResolveInScopes(item, false));
                    return(item);
                }
                else if (item.IsList && !item.IsNil)
                {
                    astAsList = item.ListValue.ToList();
                }
                else
                {
                    return(item);
                }
            }
            else
            {
                astAsList = ((IEnumerable <object>)ast).ToList();
            }

            if (astAsList.Count == 0)
            {
                return(new LispVariant(LispType.Nil));
            }

            // is this function a macro ==> process the macro and return
            if (LispEnvironment.IsMacro(astAsList.First(), scope.GlobalScope))
            {
                // check the macro modus: evaluate or expand or lambda
                var macro = LispEnvironment.GetMacro(astAsList.First(), scope.GlobalScope);

                // evaluate macro at run time:
                if (macro is LispMacroRuntimeEvaluate)
                {
                    // Example for macro at runtime handling:
                    //
                    // macro definition:
                    // (define-macro-eval my-setf (x value) (setf x value))
                    //
                    // call (ast):
                    // (my-setf a (+ \"blub\" \"xyz\"))
                    //          |         |
                    //          v         v
                    //          x        value
                    //
                    // Result:
                    // (setf a (+ \"blub\" \"xyz\"))  <-- replace formal arguments (as symbol)

                    bool anyMacroReplaced = false;
                    var  runtimeMacro     = (LispMacroRuntimeEvaluate)macro;
                    var  expression       = ReplaceFormalArgumentsInExpression(runtimeMacro.FormalArguments, astAsList, runtimeMacro.Expression, scope, ref anyMacroReplaced);

                    return(EvalAst(expression, scope));
                }

                // expand macro at compile time: --> nothing to do at run time !
                // code not needed, because code for compile time macros will be removed in ExpandMacro phase
                //if (macro is LispMacroCompileTimeExpand)
                //{
                //    return new LispVariant();
                //}

                throw new Exception("Unexpected macro modus!");
            }

            // for debugging: update the current line number at the current scope
            var currentToken = ((LispVariant)(astAsList.First())).Token;

            scope.CurrentToken = currentToken != null ? currentToken : scope.CurrentToken;

            // resolve values via local and global scope
            var astWithResolvedValues = ResolveArgsInScopes(scope, astAsList, false);

            // get first element --> this is the function !
            var function = astWithResolvedValues.First();

            // normal evaluation...
            LispFunctionWrapper functionWrapper = ((LispVariant)function).FunctionValue;

            // trace current function (if tracing is enabled)
            if (scope.GlobalScope.Tracing)
            {
                scope.GlobalScope.Output.WriteLine("--> {0}", astAsList.First());
            }

            // evaluate arguments, but allow recursive lists
            var arguments = new object[astWithResolvedValues.Count - 1];

            for (var i = 1; i < arguments.Length + 1; i++)
            {
                //var asContainer = LispUtils.GetAsContainer(astWithResolvedValues[i]);
                //var needEvaluation = (asContainer != null) && !functionWrapper.IsSpecialForm;
                //arguments[i - 1] = needEvaluation ? EvalAst(asContainer, scope) : astWithResolvedValues[i];
                var needEvaluation = (astWithResolvedValues[i] is IEnumerable <object>) &&
                                     !functionWrapper.IsSpecialForm;
                var result = needEvaluation ? EvalAst(astWithResolvedValues[i], scope) : astWithResolvedValues[i];
                // process statemens like this: `,@l  with l = (1 2 3)
                LispVariant variant = result as LispVariant;
                if (variant != null)
                {
                    if (variant.IsUnQuoted == LispUnQuoteModus.UnQuoteSplicing && variant.IsList)
                    {
                        var lst          = variant.ListRef;
                        var newArguments = new object[arguments.Length + lst.Count - 1];
                        arguments.CopyTo(newArguments, 0);
                        foreach (var elem in lst)
                        {
                            newArguments[i - 1] = elem;
                            i++;
                        }

                        arguments = newArguments;
                        break;
                    }
                }
                arguments[i - 1] = result;
            }

            // debugger processing
            var debugger = scope.GlobalScope.Debugger;

            if (debugger != null && debugger.NeedsBreak(scope, GetPosInfo(astAsList[0])))
            {
                debugger.InteractiveLoop(scope, astAsList);
            }

            // call the function with the arguments
            return(functionWrapper.Function(arguments, scope));
        }
Beispiel #25
0
 // ReSharper disable once UnusedParameter.Local
 private void DoStep(LispScope currentScope)
 {
     IsStopStepFcn = (scope) => true;
     IsProgramStop = true;
 }