コード例 #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;
                    }
コード例 #2
0
ファイル: LispExecutionState.cs プロジェクト: ixmilia/lisp
        internal bool TryDequeueOperation(out ILispEvaluatorOperation operation)
        {
            operation = default;
            if (_operationQueue.Count > 0)
            {
                operation = _operationQueue[0];
                _operationQueue.RemoveAt(0);
                return(true);
            }

            return(false);
        }
コード例 #3
0
ファイル: LispExecutionState.cs プロジェクト: ixmilia/lisp
 internal void InsertOperation(ILispEvaluatorOperation operation)
 {
     _operationQueue.Insert(0, operation);
 }