Beispiel #1
0
        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;
                    }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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());
            }
        }
Beispiel #4
0
        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"));
            });
Beispiel #5
0
        public LispObject Untrace(LispHost host, LispExecutionState executionState, LispObject[] args)
        {
            var untracedList = _repl.Untrace(args);

            return(LispList.FromItems(LispSymbol.CreateFromString("COMMON-LISP:QUOTE"), untracedList));
        }