public static LispEvaluationState Evaluate(LispHost host, LispExecutionState executionState) { var shouldDribbleReturnValue = executionState.StackFrame.Root.DribbleStream != null; while (executionState.TryDequeueOperation(out var operation)) { if (executionState.LastResult is LispError error) { // re-queue, because we can never finish executionState.InsertOperation(operation); error.StackFrame ??= executionState.StackFrame; executionState.StackFrame.Root.OnErrorOccured(error, executionState.StackFrame); return(LispEvaluationState.FatalHalt); } // value setting can only occur when evaluating a native macro or native function; if any of the set operations wants to halt, we do that below var captureValueSetHalt = false; var haltDueToValueSet = false; var valueSet = new EventHandler <LispValueSetEventArgs>((s, e) => { if (captureValueSetHalt) { haltDueToValueSet = haltDueToValueSet || e.HaltExecution; } }); executionState.StackFrame.Root.ValueSet += valueSet; switch (operation) { case LispEvaluatorPopForTailCall tailPop: { // the shape of the operation stack at the time of a tail call should be either: // pop // tail-call-expression // function-return // or // tail-call-expression // function-return ILispEvaluatorOperation tailCallExpression = null; ILispEvaluatorOperation invocationExit = null; if ((executionState.PeekOperation() is LispEvaluatorPopArgument pop && executionState.TryDequeueOperation(out var _) && executionState.PeekOperation() is LispEvaluatorObjectExpression && executionState.TryDequeueOperation(out tailCallExpression) && executionState.PeekOperation() is LispEvaluatorFunctionExit && executionState.TryDequeueOperation(out invocationExit)) || (executionState.PeekOperation() is LispEvaluatorObjectExpression && executionState.TryDequeueOperation(out tailCallExpression) && executionState.PeekOperation() is LispEvaluatorFunctionExit && executionState.TryDequeueOperation(out invocationExit))) { var concreteInvocationExit = (LispEvaluatorFunctionExit)invocationExit; Debug.Assert(ReferenceEquals(tailPop.Function, concreteInvocationExit.Function)); // restore the tail call operation and pop the stack executionState.InsertOperation(concreteInvocationExit.WithoutFramePop()); executionState.InsertOperation(tailCallExpression); executionState.StackFrame.CopyLocalsToParentForTailCall(host.CurrentPackage, new HashSet <string>(tailPop.InvocationArgumentNames)); executionState.StackFrame = executionState.StackFrame.Parent; }
public LispRepl(string location = null, TextReader input = null, TextWriter output = null, TextWriter traceWriter = null, bool useTailCalls = false) { _location = location; _input = input ?? TextReader.Null; _output = output ?? TextWriter.Null; _traceWriter = traceWriter ?? TextWriter.Null; Host = new LispHost(_location, _input, _output, useTailCalls); Host.RootFrame.FunctionEntered += FunctionEntered; Host.RootFrame.FunctionReturned += FunctionReturned; var replContext = new LispReplDefaultContext(this); Host.AddContextObject(replContext); }
public static string GetMarkdownDisplay(this LispObject obj, LispHost host) { switch (obj) { case LispCodeFunction codeFunction: return($@" ``` lisp ; <in module {codeFunction.NameSymbol.PackageName}> (DEFUN {codeFunction.NameSymbol.ToDisplayString(host.CurrentPackage)} ({codeFunction.ArgumentCollection}) ...) ``` {codeFunction.Documentation}".Trim()); case LispFunction function: return($@" ``` lisp ; <native function> ; <in module {function.NameSymbol.PackageName}> (DEFUN {function.NameSymbol.ToDisplayString(host.CurrentPackage)} (...) ...) ``` {function.Documentation}".Trim()); case LispCodeMacro codeMacro: return($@" ``` lisp ; <in module {codeMacro.NameSymbol.PackageName}> (DEFMACRO {codeMacro.NameSymbol.ToDisplayString(host.CurrentPackage)} ({codeMacro.ArgumentCollection}) ...) ``` TODO: documentation".Trim()); case LispMacro macro: return($@" ``` lisp ; <native macro> ; <in module {macro.NameSymbol.PackageName}> (DEFMACRO {macro.NameSymbol.ToDisplayString(host.CurrentPackage)} (...) ...) ``` TODO: documentation".Trim()); case LispResolvedSymbol symbol: // TODO: don't display current package qualifier return($"`{symbol.Value}`: {host.GetValue(symbol.Value)}"); default: return(obj?.ToString()); } }
public LispObjectReader(LispHost host) { _host = host; _host.AddFunction("SET-MACRO-CHARACTER", (__host, executionState, args) => { if (args.Length == 2 && args[0] is LispCharacter character && args[1] is LispFunctionReference functionRef) { _macroFunctions.Add(character.Value, functionRef); return(__host.Nil); } return(new LispError("Expected character and function reference")); });
public LispObject Untrace(LispHost host, LispExecutionState executionState, LispObject[] args) { var untracedList = _repl.Untrace(args); return(LispList.FromItems(LispSymbol.CreateFromString("COMMON-LISP:QUOTE"), untracedList)); }