public DekiScriptOutputBuffer.Range Visit(DekiScriptTryCatchFinally expr, DekiScriptExpressionEvaluationState state)
        {
            int marker = state.Buffer.Marker;

            try {
                expr.Try.VisitWith(this, state);
            } catch (DekiScriptFatalException) {
                throw;
            } catch (DekiScriptControlFlowException) {
                throw;
            } catch (Exception e) {
                state.Buffer.Reset(marker);

                // translate exception to an error object
                DekiScriptMap error = DekiScriptLibrary.MakeErrorObject(e, state.Env);

                // capture error object in a nested environment
                try {
                    state.Env.Vars.Add(expr.Variable, error);
                    expr.Catch.VisitWith(this, state);
                } finally {
                    state.Env.Vars.Add(expr.Variable, DekiScriptNil.Value);
                }
            } finally {
                expr.Finally.VisitWith(this, state);
            }
            return(state.Buffer.Since(marker));
        }
        public void ThrowIfTimedout()
        {
            if (_sharedState.EvaluationTimer == null)
            {
                return;
            }
            if (_sharedState.EvaluationTimer.Elapsed <= _sharedState.EvaluationTimeout)
            {
                return;
            }
            _sharedState.EvaluationTimer.Stop();
            var e     = new TimeoutException("script execution has timed out");
            var error = DekiScriptLibrary.MakeErrorObject(e, Env);

            _sharedState.EvaluationError = new DekiScriptXml(DekiScriptLibrary.WebShowError((Hashtable)error.NativeValue));
            throw e;
        }
        public DekiScriptOutputBuffer.Range Visit(DekiScriptReturnScope expr, DekiScriptExpressionEvaluationState state)
        {
            int marker = state.Buffer.Marker;

            try {
                if (state.FatalEvaluationError == null)
                {
                    state.ThrowIfTimedout();
                    return(expr.Value.VisitWith(this, state));
                }
                state.Push(state.FatalEvaluationError);
            } catch (DekiScriptReturnException e) {
                state.Push(e.Value);
            } catch (DekiScriptControlFlowException) {
                // nothing to do
            } catch (Exception e) {
                var error = DekiScriptLibrary.MakeErrorObject(e, state.Env);
                state.Runtime.LogExceptionInOutput(error);
                state.Push(new DekiScriptXml(DekiScriptLibrary.WebShowError((Hashtable)error.NativeValue)));
            }
            return(state.Buffer.Since(marker));
        }