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); }
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); }
protected internal virtual void OnEndNotifyCall(StackFrame stackFrame, ConsNode cons, LispFunc func, string funcName, object res) { if (EndNotifyCall != null) { EndNotifyCall(stackFrame, cons, func, funcName, res); } }
protected internal virtual void OnBeginNotifyCall(StackFrame stackFrame, ConsNode cons, LispFunc func, string funcName) { if (BeginNotifyCall != null) { BeginNotifyCall(stackFrame, cons, func, funcName); } }
public static ConsNode NewCons(RuntimeStack stack) { var resNode = new ConsNode(); resNode.HideFromCallstack = true; resNode.Stack = stack; return(resNode); }
public StackFrame(StackFrame previousStackFrame, ConsNode cons) { PreviousStackFrame = previousStackFrame; Cons = cons; if (previousStackFrame != null) { Root = previousStackFrame.Root; Scope = previousStackFrame.Scope; } }
public void Parse(string code) { try { ParseInfo info = SetupParseInfo(code, "user", false); root = Parser.Parse(info); // Cons rootCons = Parser.MakeSExpression(root); } catch { throw; } }
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); }
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); ////} }
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; } }
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); }
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); }
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); }
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++; } }
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); }
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); }
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); //} }
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)); }