Пример #1
0
        private ValueNode ParseQuote(ParseInfo info, ref int index)
        {
            var node = new ConsNode();

            node.Args = new List <object>();
            var idNode = new SymbolNode();

            idNode.Name           = "quote";
            idNode.CodeStartIndex = index;
            idNode.CodeLength     = 1;
            SetupNode(info, idNode);
            node.Args.Add(idNode);


            node.CodeStartIndex = index;
            index++;
            object expression = ParseArg(info, ref index);

            node.Args.Add(expression);

            node.CodeLength = index - node.CodeStartIndex;
            SetupNode(info, node);

            return(node);
        }
Пример #2
0
        public static object Defun(FunctionInvocation call)
        {
            var func        = call.Args[1] as SymbolNode;
            var definedArgs = call.Args[2] as ConsNode;
            //ConsNode definedBody = call.Args[3] as ConsNode;

            ConsNode definedBody = WrapInProgn(call.Args, 3, call.StackFrame.Root);

            Scope creatorScope = call.StackFrame.Scope;

            LispFunc lispFunc = kall =>
            {
                //if (kall.Args.Count - 1 < definedArgs.Args.Count)
                //{
                //    LispFunc curryFunc = MakeCurryCall(call, definedArgs, definedBody, kall);

                //    return curryFunc;
                //}
                //else
                //{
                Scope oldScope = kall.StackFrame.Scope;
                var   newScope = new Scope(creatorScope);
                Utils.SetupArgs(definedArgs, kall, newScope);
                kall.StackFrame.Scope = newScope;

                //call the body
                object res = definedBody.Eval(kall.StackFrame);

                //tail recursion
                int recursions = 0;
                while (res is TailRecursionValue)
                {
                    recursions++;

                    var tail     = res as TailRecursionValue;
                    var tailCons = tail.Expression as ConsNode;

                    newScope  = new Scope(creatorScope);
                    kall.Args = tailCons.Args;
                    Utils.SetupArgs(definedArgs, kall, newScope);
                    kall.StackFrame.Scope = newScope;


                    res = definedBody.Eval(kall.StackFrame);
                }

                Utils.TearDownArgs(definedArgs, kall);
                kall.StackFrame.Scope = oldScope;

                return(res);
                //}
            };

            call.StackFrame.Scope.SetSymbolValue(func.Name, lispFunc);
            //      FunctionMeta meta = call.StackFrame.Root.GetFunctionMeta(lispFunc);
            //      meta.ParameterCount = definedArgs.Args.Count;

            return(null);
        }
Пример #3
0
 protected internal virtual void OnEndNotifyCall(StackFrame stackFrame, ConsNode cons, LispFunc func,
                                                 string funcName, object res)
 {
     if (EndNotifyCall != null)
     {
         EndNotifyCall(stackFrame, cons, func, funcName, res);
     }
 }
Пример #4
0
 protected internal virtual void OnBeginNotifyCall(StackFrame stackFrame, ConsNode cons, LispFunc func,
                                                   string funcName)
 {
     if (BeginNotifyCall != null)
     {
         BeginNotifyCall(stackFrame, cons, func, funcName);
     }
 }
Пример #5
0
        public static ConsNode NewCons(RuntimeStack stack)
        {
            var resNode = new ConsNode();

            resNode.HideFromCallstack = true;
            resNode.Stack             = stack;
            return(resNode);
        }
Пример #6
0
        public StackFrame(StackFrame previousStackFrame, ConsNode cons)
        {
            PreviousStackFrame = previousStackFrame;
            Cons = cons;

            if (previousStackFrame != null)
            {
                Root  = previousStackFrame.Root;
                Scope = previousStackFrame.Scope;
            }
        }
Пример #7
0
 public void Parse(string code)
 {
     try
     {
         ParseInfo info = SetupParseInfo(code, "user", false);
         root = Parser.Parse(info);
         //     Cons rootCons = Parser.MakeSExpression(root);
     }
     catch
     {
         throw;
     }
 }
Пример #8
0
        public Engine()
        {
            Stack        = new RuntimeStack();
            Stack.Engine = this;
            Parser       = new LispParser();

            CoreConfigurator.Configure(Stack);

            ParseInfo info = SetupParseInfo(Resources.CoreLib.Replace("\r\n", "\n"), "core", true);

            ConsNode root = Parser.Parse(info);

            root.Eval(Stack.StackFrame);
        }
Пример #9
0
        public static void TearDownArgs(ConsNode definedArgs, FunctionInvocation call)
        {
            //int i = 1;
            ////tear down args
            //foreach (IdentifierNode arg in definedArgs.Args)
            //{
            //    string argName = arg.Name;

            //    if (argName.StartsWith("*"))
            //    {
            //        argName = argName.Substring(1);
            //        call.StackFrame.PopSymbol(argName);
            //    }
            //    else if (argName.StartsWith("!"))
            //    {
            //        argName = argName.Substring(1);
            //        call.StackFrame.PopSymbol(argName);
            //    }
            //    else if (argName.StartsWith("#"))
            //    {
            //        argName = argName.Substring(1);
            //        call.StackFrame.PopSymbol(argName);
            //    }
            //    else if (argName.StartsWith("@"))
            //    {
            //        argName = argName.Substring(1);
            //        call.StackFrame.PopSymbol(argName);
            //    }
            //    else if (argName.StartsWith(":"))
            //    {

            //    }
            //    else
            //    {
            //        call.StackFrame.PopSymbol(argName);
            //    }


            //    i++;
            //}

            ////for (int j = i; j < call.Args.Count; j++)
            ////{
            ////    ValueNode node = call.Args[j];
            ////    string argName = string.Format("arg{0}", j);
            ////    stack.PopSymbol(argName);
            ////}
        }
Пример #10
0
        public object EvaluateString(string code, string codeName)
        {
            try
            {
                ParseInfo info = SetupParseInfo(code, codeName, false);
                ConsNode  node = Parser.Parse(info);

                //          Cons rootCons = Parser.MakeSExpression(node);

                return(node.Eval(Stack.StackFrame));
            }
            catch
            {
                throw;
            }
        }
Пример #11
0
        private ConsNode ParseFunction(ParseInfo info, ref int index)
        {
            var funcNode = new ConsNode();

            SetupNode(info, funcNode);
            funcNode.CodeStartIndex = index;

            EnsureToken(info, ref index, "(");
            List <object> args = ParseArgs(info, ref index);

            funcNode.Args = args;
            index++;
            funcNode.CodeLength = index - funcNode.CodeStartIndex;

            return(funcNode);
        }
Пример #12
0
        public static object Reverse(FunctionInvocation call)
        {
            var list = Utils.Eval(call.StackFrame, call.Args[1]) as IEnumerable;

            var res = new List <object>();

            foreach (object item in list)
            {
                res.Add(item);
            }

            res.Reverse();

            ConsNode resNode = Utils.NewCons(call.StackFrame.Root);

            resNode.Args = res;
            return(resNode);
        }
Пример #13
0
        private static ConsNode WrapInProgn(List <object> args, int startIndex, RuntimeStack stack)
        {
            var definedBody = new ConsNode();

            definedBody.Stack             = stack;
            definedBody.HideFromCallstack = true;
            definedBody.Code     = "";
            definedBody.CodeName = "runtime";
            definedBody.Args     = new List <object>();

            var progn = new SymbolNode();

            progn.Name              = "progn";
            progn.Stack             = stack;
            progn.HideFromCallstack = true;
            progn.Code              = "";
            progn.CodeName          = "runtime";

            definedBody.Args.Add(progn);
            definedBody.Args.AddRange(args.GetRange(startIndex, args.Count - startIndex));
            return(definedBody);
        }
Пример #14
0
        public static void SetupMacroArgs(ConsNode definedArgs, FunctionInvocation call, Scope newScope)
        {
            int i = 1;

            //todo: verify arg list, only identifiers allowed

            //setup local args
            for (int argIndex = 0; argIndex < definedArgs.Args.Count; argIndex++)
            {
                var arg = definedArgs.Args[argIndex] as SymbolNode;

                string argName = arg.Name;

                if (argName == "&optional")
                {
                }
                else if (argName == "&rest")
                {
                    argIndex++;
                    var    restArg  = definedArgs.Args[argIndex] as SymbolNode;
                    string restName = restArg.Name;

                    ConsNode restCons = NewCons(call.StackFrame.Root);
                    restCons.Args = call.Args.Skip(i).ToList();

                    newScope.PushSymbol(restName).Value = restCons;
                }
                else
                {
                    Symbol symbol  = newScope.PushSymbol(argName);
                    object bodyArg = call.Args[i];
                    symbol.Value = bodyArg;
                }
                i++;
            }
        }
Пример #15
0
        public static object Cdr(FunctionInvocation call)
        {
            var list = Utils.Eval(call.StackFrame, call.Args[1]) as IEnumerable;

            bool first = true;
            var  res   = new List <object>();

            foreach (object item in list)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    res.Add(item);
                }
            }

            ConsNode resNode = Utils.NewCons(call.StackFrame.Root);

            resNode.Args = res;
            return(resNode);
        }
Пример #16
0
        public static object Lambda(FunctionInvocation call)
        {
            ConsNode definedArgs = null;
            ConsNode definedBody = null;

            var info = new CloneInfo();

            info.StackFrame = call.StackFrame;
            Scope creatorScope = call.StackFrame.Scope;


            ValueNode bodyNode = null;

            if (call.Args.Count == 2)
            {
                definedArgs      = new ConsNode();
                definedArgs.Args = new List <object>();
                var varNode = new SymbolNode();
                varNode.Name = "item";
                definedArgs.Args.Add(varNode);
                bodyNode = call.Args[1] as ConsNode;
            }
            else if (call.Args.Count == 3)
            {
                if (call.Args[1] is ConsNode)
                {
                    definedArgs = call.Args[1] as ConsNode;
                }
                else
                {
                    definedArgs = Utils.Eval(call.StackFrame, call.Args[1]) as ConsNode;
                }

                bodyNode = call.Args[2] as ConsNode;
            }

            info.LocalIdentifiers =
                definedArgs.Args.Cast <SymbolNode>().Select(arg => Utils.CleanName(arg.Name)).ToList();

            //make snapshot of bound non local identifiers
            definedBody = bodyNode.Clone(info) as ConsNode;

            LispFunc lispFunc = kall =>
            {
                //todo: verify arg list, only identifiers allowed
                Scope oldScope = kall.StackFrame.Scope;
                var   newScope = new Scope(creatorScope);
                Utils.SetupArgs(definedArgs, kall, newScope);
                kall.StackFrame.Scope = newScope;


                //call the body
                object res = definedBody.Eval(kall.StackFrame);


                Utils.TearDownArgs(definedArgs, kall);
                kall.StackFrame.Scope = oldScope;

                return(res);
            };

            return(lispFunc);
        }
Пример #17
0
        public static void SetupArgs(ConsNode definedArgs, FunctionInvocation call, Scope newScope)
        {
            int i = 1;

            //todo: verify arg list, only identifiers allowed

            //setup local args
            for (int argIndex = 0; argIndex < definedArgs.Args.Count; argIndex++)
            {
                var arg = definedArgs.Args[argIndex] as SymbolNode;

                string argName = arg.Name;

                if (argName == "&optional")
                {
                }
                else if (argName == "&rest")
                {
                    argIndex++;
                    var    restArg  = definedArgs.Args[argIndex] as SymbolNode;
                    string restName = restArg.Name;

                    ConsNode restCons = NewCons(call.StackFrame.Root);
                    restCons.Args = call.EvalArgs(i);

                    newScope.PushSymbol(restName).Value = restCons;
                }
                else if (argName[0] == '*')
                {
                    //ref symbol
                    var argId = call.Args[i] as SymbolNode;
                    argName = argName.Substring(1);
                    if (argId == null)
                    {
                        throw new Exception(
                                  string.Format("Argument '{0}' is defined as a pointer, but passed as a value", argName));
                    }

                    Symbol sourceVar = argId.GetSymbol(call.StackFrame);

                    newScope.DeclareRef(argName, sourceVar);
                }
                else if (argName[0] == '!')
                {
                    argName = argName.Substring(1);
                    newScope.PushSymbol(argName);
                    var bodyArg = call.Args[i] as ValueNode;
                    newScope.SetSymbolValue(argName, bodyCall => bodyArg.Eval(call.StackFrame));
                }
                else if (argName[0] == '#')
                {
                    argName = argName.Substring(1);
                    Symbol symbol  = newScope.PushSymbol(argName);
                    object bodyArg = call.Args[i];
                    symbol.Value = bodyArg;
                }
                else if (argName[0] == ':')
                {
                    var argId = call.Args[i] as SymbolNode;
                    argName = argName.Substring(1);
                    if (argId == null)
                    {
                        throw new Exception(
                                  string.Format("Argument '{0}' is defined as a verbatim, but passed as a value", argName));
                    }
                    if (argId.Name != argName)
                    {
                        throw new Exception(string.Format("Argument '{0}' is defined as a verbatim, but passed as {1}",
                                                          argName, argId.Name));
                    }
                }
                else if (argName[0] == '@')
                {
                    var    argId    = call.Args[i] as SymbolNode;
                    object argValue = argId.Name;
                    argName = argName.Substring(1);
                    newScope.PushSymbol(argName).Value = argValue;
                }
                else
                {
                    //normal var
                    object argValue = Eval(call.StackFrame, call.Args[i]);
                    newScope.PushSymbol(argName).Value = argValue;
                }
                i++;
            }

            //for (int j = i; j < call.Args.Count; j++)
            //{
            //    ValueNode node = call.Args[j];
            //    string argName = string.Format("arg{0}", j);
            //    object argValue = node.GetValue(stack);
            //    stack.PushSymbol(argName);
            //    stack.Scope.SetSymbolValue(argName, argValue);
            //}
        }
Пример #18
0
        public static object EvalFormula(FunctionInvocation call)
        {
            bool dirty = true;

            var tmpNode = new ConsNode();

            tmpNode.Args     = call.Args.GetRange(1, call.Args.Count - 1);
            tmpNode.Stack    = call.StackFrame.Root;
            tmpNode.CodeName = "runtime";


            while (dirty)
            {
                int        bestPrio  = 0;
                SymbolNode bestNode  = null;
                int        bestIndex = 0;
                for (int i = 1; i < tmpNode.Args.Count; i++)
                {
                    var operatorId = tmpNode.Args[i] as SymbolNode;
                    if (operatorId != null)
                    {
                        var func = operatorId.Eval(call.StackFrame) as LispFunc;
                        if (func == null)
                        {
                            continue;
                        }

                        if (call.StackFrame.Root.OperatorPriority.ContainsKey(func))
                        {
                            int operatorPrio = call.StackFrame.Root.OperatorPriority[func];
                            if (bestNode == null || operatorPrio > bestPrio)
                            {
                                bestPrio  = operatorPrio;
                                bestNode  = operatorId;
                                bestIndex = i;
                            }
                        }
                    }
                }

                if (bestNode != null)
                {
                    object left  = tmpNode.Args[bestIndex - 1];
                    object right = tmpNode.Args[bestIndex + 1];
                    var    op    = tmpNode.Args[bestIndex] as SymbolNode;

                    if (tmpNode.Args.Count == 3)
                    {
                        tmpNode.Args.Clear();
                        tmpNode.Args.Add(op);
                        tmpNode.Args.Add(left);
                        tmpNode.Args.Add(right);
                    }
                    else
                    {
                        var newNode = new ConsNode();
                        newNode.Code              = op.Code;
                        newNode.CodeStartIndex    = op.CodeStartIndex - 1;
                        newNode.CodeLength        = op.CodeLength;
                        newNode.CodeName          = "runtime";
                        newNode.HideFromCallstack = op.HideFromCallstack;

                        newNode.Args = new List <object>();
                        newNode.Args.Add(op);
                        newNode.Args.Add(left);
                        newNode.Args.Add(right);
                        newNode.Stack = call.StackFrame.Root;

                        tmpNode.Args.RemoveRange(bestIndex - 1, 3);
                        tmpNode.Args.Insert(bestIndex - 1, newNode);
                    }
                }
                else if (bestNode == null)
                {
                    dirty = false;
                }
            }

            return(tmpNode.Eval(call.StackFrame));
        }