Пример #1
0
        public void ExecutionCannotBeHaltedWhenEvaluatingFromWithinANativeMacro()
        {
            var host = new LispHost();

            host.AddMacro("NATIVE-FUNCTION", (host, executionState, args) =>
            {
                var result = host.EvalAtStackFrame(executionState.StackFrame, LispList.FromEnumerable(new LispObject[] { LispSymbol.CreateFromString("*"), new LispInteger(2), new LispInteger(2) }));
                return(result);
            });
            var hitBreakpoint = false;

            host.RootFrame.EvaluatingExpression += (s, e) =>
            {
                if (!hitBreakpoint &&
                    e.Expression is LispList list &&
                    list.ToString() == "(* 2 2)")
                {
                    hitBreakpoint   = true;
                    e.HaltExecution = true; // this should not be honored
                }
            };
            var evalResult = host.Eval("(native-function)");

            Assert.True(hitBreakpoint);
            Assert.True(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal(4, ((LispInteger)evalResult.LastResult).Value);
        }
Пример #2
0
        public void PackagesCanInheritSymbols()
        {
            var host   = new LispHost(useInitScript: false);
            var result = host.Eval(@"
(defpackage :a)
(in-package :a)
(setf aa 1)

(defpackage :b
    (:use :a))
(in-package :b)
(setf bb 2)

(defpackage :x)
(in-package :x)
(setf xx 3)

(defpackage :c
    (:use :b :x))
(in-package :c)
(list aa  ; a:aa => 1
      bb  ; b:bb => 2
      xx) ; x:xx => 3
");

            Assert.Equal("(1 2 3)", result.LastResult.ToString());
        }
Пример #3
0
        public void ErrorStackPropagationFromInitScript()
        {
            var host            = new LispHost();
            var evalResult      = host.Eval("*REPL*", "(+ 1 \"two\" 3)");
            var error           = (LispError)evalResult.LastResult;
            var errorStackFrame = error.StackFrame;

            Assert.Equal("KERNEL:+/2", errorStackFrame.FunctionSymbol.Value);
            Assert.Null(errorStackFrame.SourceLocation); // in native code

            Assert.Equal("REDUCE", errorStackFrame.Parent.FunctionSymbol.LocalName);
            Assert.Null(errorStackFrame.Parent.SourceLocation); // in native code

            // this function can move around, but the body is one line below the definition
            var plusFunction         = host.GetValue <LispFunction>("+");
            var plusFunctionLocation = plusFunction.SourceLocation.Value;

            Assert.Equal("+", errorStackFrame.Parent.Parent.FunctionSymbol.LocalName);
            Assert.Equal(new LispSourceLocation("init.lisp", new LispSourcePosition(plusFunctionLocation.Start.Line + 1, 34), new LispSourcePosition(plusFunctionLocation.Start.Line + 1, 40)), errorStackFrame.Parent.Parent.SourceLocation);

            Assert.Equal("(ROOT)", errorStackFrame.Parent.Parent.Parent.FunctionSymbol.LocalName);
            Assert.Equal(new LispSourceLocation("*REPL*", new LispSourcePosition(1, 12), new LispSourcePosition(1, 13)), errorStackFrame.Parent.Parent.Parent.SourceLocation);
            // TODO: [(1, 6)-(1, 11)) is better since that argument isn't a number

            Assert.Null(errorStackFrame.Parent.Parent.Parent.Parent);
        }
Пример #4
0
        public void ExecutionCanBeHaltedWhenAnErrorIsExplicitlyRaised()
        {
            var       host          = new LispHost();
            LispError capturedError = null;

            host.RootFrame.ErrorOccured += (s, e) =>
            {
                capturedError = e.Error;
            };
            var evalResult = host.Eval(@"
(defun test-method ()
    (error ""test error""))
(test-method)
");

            // errors _always_ halt execution
            Assert.False(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal("test error", ((LispError)evalResult.LastResult).Message);
            Assert.Equal("test error", capturedError.Message);
            Assert.True(ReferenceEquals(capturedError, evalResult.LastResult));

            // all future processing stops
            host.EvalContinue(evalResult.ExecutionState);
            Assert.False(evalResult.ExecutionState.IsExecutionComplete);
        }
Пример #5
0
        public void HaltExecutionOnFunctionEnter()
        {
            var host = new LispHost();

            host.RootFrame.FunctionEntered += (s, e) =>
            {
                if (e.Frame.FunctionSymbol.Value == "COMMON-LISP-USER:INNER-FUNCTION")
                {
                    e.HaltExecution = true;
                }
            };
            var evalResult = host.Eval(@"
(defun inner-function ()
    42)
(defun outer-function ()
    (inner-function))
(outer-function)
");

            Assert.False(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Null(evalResult.LastResult);
            host.EvalContinue(evalResult.ExecutionState);
            Assert.True(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal(42, ((LispInteger)evalResult.LastResult).Value);
        }
Пример #6
0
        public void ExecutionCanBeHaltedWhenAnErrorIsNaturallyEncountered()
        {
            var       host          = new LispHost();
            LispError capturedError = null;

            host.RootFrame.ErrorOccured += (s, e) =>
            {
                capturedError = e.Error;
            };
            var evalResult = host.Eval(@"
(defun test-method ()
    (not-a-method))
(test-method)
");

            // errors _always_ halt execution
            Assert.False(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal("Undefined macro/function 'NOT-A-METHOD', found '<null>'", ((LispError)evalResult.LastResult).Message);
            Assert.Equal("Undefined macro/function 'NOT-A-METHOD', found '<null>'", capturedError.Message);
            Assert.True(ReferenceEquals(capturedError, evalResult.LastResult));

            // all future processing stops
            host.EvalContinue(evalResult.ExecutionState);
            Assert.False(evalResult.ExecutionState.IsExecutionComplete);
        }
Пример #7
0
        public void KeywordSymbolsImmediatelyResolveToThemselves()
        {
            var host   = new LispHost(useInitScript: false);
            var result = host.Eval(":some-keyword");

            Assert.Equal(new LispResolvedSymbol("KEYWORD", "SOME-KEYWORD", isPublic: true), result.LastResult);
        }
Пример #8
0
        public void HaltExecutionOnMacroExpansion()
        {
            var host = new LispHost();

            host.AddMacro("FOURTY-TWO", (host, executionState, args) =>
            {
                return(new LispInteger(42));
            });
            host.RootFrame.MacroExpanded += (s, e) =>
            {
                if (e.Macro.NameSymbol.LocalName == "FOURTY-TWO")
                {
                    e.HaltExecution = true;
                }
            };
            var evalResult = host.Eval(@"
(fourty-two)
(+ 1 2)
");

            Assert.False(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal("s: 42", evalResult.ExecutionState.PeekOperation().ToString());

            host.EvalContinue(evalResult.ExecutionState);
            Assert.True(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal(3, ((LispInteger)evalResult.LastResult).Value);
        }
Пример #9
0
        public void ExecutionCanStepOut(bool useTailCalls)
        {
            var host      = new LispHost(useTailCalls: useTailCalls);
            var hasHalted = false;

            host.RootFrame.EvaluatingExpression += (s, e) =>
            {
                if (!hasHalted && e.Expression.ToString() == "(+ 1 1)")
                {
                    e.HaltExecution = true;
                    hasHalted       = true;
                }
            };
            var evalResult = host.Eval(@"
(defun test-method ()
    (+ 1 1) ; initial halt here
    (+ 2 2))
(test-method)
(+ 3 3)
(+ 4 4)
");

            Assert.False(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal("s: (+ 1 1)", evalResult.ExecutionState.PeekOperation().ToString());

            host.StepOut(evalResult.ExecutionState);
            Assert.False(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal("s: (+ 3 3)", evalResult.ExecutionState.PeekOperation().ToString());

            host.StepOut(evalResult.ExecutionState); // can't step out at the root level; this was really a run to end
            Assert.True(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal(8, ((LispInteger)evalResult.LastResult).Value);
        }
Пример #10
0
        public void HaltExecutionOnEvaluatingFunctionArgument()
        {
            var host          = new LispHost();
            var hitBreakpoint = false;

            host.RootFrame.EvaluatingExpression += (s, e) =>
            {
                if (!hitBreakpoint &&
                    e.Expression is LispList list &&
                    list.ToString() == "(* 2 2)")
                {
                    hitBreakpoint   = true;
                    e.HaltExecution = true;
                }
            };
            var evalResult = host.Eval(@"
(+ (* 2 2) (* 3 3))
");

            Assert.True(hitBreakpoint);
            Assert.False(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Null(evalResult.LastResult);
            host.EvalContinue(evalResult.ExecutionState);
            Assert.True(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal(13, ((LispInteger)evalResult.LastResult).Value);
        }
Пример #11
0
        public void ExecutionStepInWhenNextOperationIsNotAnExpression()
        {
            var host = new LispHost();

            host.RootFrame.FunctionReturned += (s, e) =>
            {
                if (e.Frame.FunctionSymbol.Value == "COMMON-LISP-USER:TEST-METHOD")
                {
                    e.HaltExecution = true;
                }
            };
            var evalResult = host.Eval(@"
(defun test-method ()
    (+ 1 2))
(test-method)
(+ 4 5)
");

            Assert.False(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal(3, ((LispInteger)evalResult.LastResult).Value);
            Assert.Null(evalResult.ExecutionState.PeekCurrentExpression());

            host.StepIn(evalResult.ExecutionState); // nothing to step in to, so it's really step out _then_ step in
            Assert.False(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal("s: 4", evalResult.ExecutionState.PeekOperation().ToString());

            host.EvalContinue(evalResult.ExecutionState);
            Assert.True(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal(9, ((LispInteger)evalResult.LastResult).Value);;
        }
Пример #12
0
        public void ExternalFunction()
        {
            var host = new LispHost();

            host.AddFunction("ADD", (host, executionState, args) => (LispInteger)args[0] + (LispInteger)args[1]);
            Assert.Equal(new LispInteger(3), host.Eval("(add 1 2)").LastResult);
        }
Пример #13
0
        public void ExecutionStepOutWhenNextOperationIsNotAnExpression()
        {
            var host = new LispHost();

            host.RootFrame.FunctionReturned += (s, e) =>
            {
                if (e.Frame.FunctionSymbol.Value == "COMMON-LISP-USER:TEST-METHOD")
                {
                    e.HaltExecution = true;
                }
            };
            var evalResult = host.Eval(@"
(defun test-method ()
    (+ 1 2))
(test-method)
(+ 4 5)
");

            Assert.False(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal(3, ((LispInteger)evalResult.LastResult).Value);
            Assert.Null(evalResult.ExecutionState.PeekCurrentExpression());

            host.StepOut(evalResult.ExecutionState); // stepping out here steps out of everything
            Assert.True(evalResult.ExecutionState.IsExecutionComplete);
            Assert.Equal(9, ((LispInteger)evalResult.LastResult).Value);;
        }
Пример #14
0
        public void DotNotationLists()
        {
            var host   = new LispHost();
            var result = host.Eval("'(a . (b . (c)))").LastResult;
            var actual = result.ToString();

            Assert.Equal("(A B C)", actual);
        }
Пример #15
0
        public void InvokeBuiltInNamedFunctionReference()
        {
            var host     = new LispHost();
            var result   = host.Eval(@"(funcall #'cons 'a 'b)").LastResult;
            var expected = LispList.FromItemsImproper(LispSymbol.CreateFromString("A"), LispSymbol.CreateFromString("B"));

            Assert.Equal(expected, result);
        }
Пример #16
0
        public void SourceLocationIsNotPropagatedFromComputedValues2()
        {
            var host   = new LispHost("host.lisp");
            var result = host.Eval("some-other-location.lisp", "(+ 1 2)").LastResult;

            Assert.Equal(3, ((LispInteger)result).Value);
            Assert.Null(result.SourceLocation);
        }
Пример #17
0
        public void SingleItem()
        {
            var host = new LispHost();

            Assert.Equal(new LispInteger(3), host.Eval("3").LastResult);
            Assert.Equal(new LispFloat(3.0), host.Eval("3.0").LastResult);
            Assert.Equal(new LispString("a"), host.Eval("\"a\"").LastResult);
        }
Пример #18
0
        private void EvalFile(string fileName)
        {
            var contents = GetFileContents(fileName);
            var host     = new LispHost();
            var result   = host.Eval(contents);

            Assert.True(result.LastResult.Equals(host.T), result.LastResult.ToString());
        }
Пример #19
0
        public void InvokeLambdaFromReference()
        {
            var host   = new LispHost();
            var result = host.Eval(@"
(funcall #'(lambda (n) (+ 1 n)) 2)
").LastResult;

            Assert.Equal(new LispInteger(3), result);
        }
Пример #20
0
        public void PackageIsCreatedWithDefPackageWithString()
        {
            var host = new LispHost();

            host.Eval("(defpackage \"TEST-PACKAGE\") (in-package :test-package)");
            var package = host.GetValue <LispPackage>("*PACKAGE*");

            Assert.Equal("TEST-PACKAGE", package.Name);
        }
Пример #21
0
        public void ErrorGeneration()
        {
            var host   = new LispHost();
            var result = host.Eval(@"
(error ""Expected '~s' but got '~s'"" 1 2)
").LastResult;

            Assert.Equal("Expected '1' but got '2'", ((LispError)result).Message);
        }
Пример #22
0
        public void Quoted()
        {
            var host = new LispHost();

            Assert.Equal(LispSymbol.CreateFromString("A"), host.Eval("'a").LastResult);
            Assert.Equal(LispList.FromItems(new LispUnresolvedSymbol("QUOTE"), LispSymbol.CreateFromString("A")), host.Eval("''a").LastResult);
            Assert.Equal(LispList.FromItems(new LispInteger(1)), host.Eval("'(1)").LastResult);
            Assert.Equal("(QUOTE A)", host.Eval("(eval '''a)").LastResult.ToString());
        }
Пример #23
0
        public void ApplyFunctionReference()
        {
            var host   = new LispHost();
            var result = host.Eval(@"
(apply #'+ '(2 3))
").LastResult;

            Assert.Equal(5, ((LispInteger)result).Value);
        }
Пример #24
0
        public void PackageIsCreatedWithDefPackageWithKeyword()
        {
            var host = new LispHost(useInitScript: false);

            host.Eval("(defpackage :test-package) (in-package :test-package)");
            var package = host.GetValue <LispPackage>("*PACKAGE*");

            Assert.Equal("TEST-PACKAGE", package.Name);
        }
Пример #25
0
        public void MixedNumericFolding()
        {
            var host = new LispHost();

            Assert.Equal(new LispFloat(10.0), host.Eval("(+ 1.0 2 3 4)").LastResult);
            Assert.Equal(new LispFloat(10.0), host.Eval("(+ 1 2.0 3 4)").LastResult);
            Assert.Equal(new LispRatio(5, 4), host.Eval("(+ (/ 1 4) 1)").LastResult);
            Assert.Equal(new LispRatio(5, 4), host.Eval("(+ 1 (/ 1 4))").LastResult);
        }
Пример #26
0
        public void FormatOutputWithArgument()
        {
            var output = new StringWriter();
            var host   = new LispHost(output: output);

            host.Eval(@"(format t ""hello ~S"" ""world"")");
            var result = NormalizeNewlines(output.ToString());

            Assert.Equal("hello \"world\"", result);
        }
Пример #27
0
        public void InvokeLambdaFromSymbol()
        {
            var host   = new LispHost();
            var result = host.Eval(@"
(setf inc-function #'(lambda (n) (+ 1 n)))
(funcall inc-function 2)
").LastResult;

            Assert.Equal(new LispInteger(3), result);
        }
Пример #28
0
        public void FloatNumericFolding()
        {
            var host = new LispHost();

            Assert.Equal(new LispFloat(-4.0), host.Eval("(- 4.0)").LastResult);
            Assert.Equal(new LispFloat(10.0), host.Eval("(+ 1.0 2.0 3.0 4.0)").LastResult);
            Assert.Equal(new LispFloat(1.0), host.Eval("(- 10.0 4.0 3.0 2.0)").LastResult);
            Assert.Equal(new LispFloat(24.0), host.Eval("(* 1.0 2.0 3.0 4.0)").LastResult);
            Assert.Equal(new LispFloat(4.0), host.Eval("(/ 24.0 3.0 2.0)").LastResult);
        }
Пример #29
0
        public void IntegerNumericFolding()
        {
            var host = new LispHost();

            Assert.Equal(new LispInteger(-4), host.Eval("(- 4)").LastResult);
            Assert.Equal(new LispInteger(10), host.Eval("(+ 1 2 3 4)").LastResult);
            Assert.Equal(new LispInteger(1), host.Eval("(- 10 4 3 2)").LastResult);
            Assert.Equal(new LispInteger(24), host.Eval("(* 1 2 3 4)").LastResult);
            Assert.Equal(new LispInteger(4), host.Eval("(/ 24 3 2)").LastResult);
        }
Пример #30
0
        private LispObject Read(string text)
        {
            var host  = new LispHost();
            var input = new LispTextStream("", new StringReader(text), TextWriter.Null);

            host.ObjectReader.SetReaderStream(input);
            var result = host.ObjectReader.Read(false, new LispError("EOF"), false);

            return(result.LastResult);
        }