public void PackageGlobalVariableIsUpdatedWithHostProperty() { var host = new LispHost(useInitScript: false); var testPackage = host.AddPackage("TEST-PACKAGE", new[] { host.CurrentPackage }); var package = host.GetValue <LispPackage>("*PACKAGE*"); Assert.Equal("COMMON-LISP", package.Name); host.CurrentPackage = testPackage; package = host.GetValue <LispPackage>("*PACKAGE*"); Assert.Equal("TEST-PACKAGE", package.Name); }
public void CurrentPackageIsUpdatedWithInPackageFunctionWithString() { var host = new LispHost(); host.AddPackage("TEST-PACKAGE", new[] { host.CurrentPackage }); var package = host.GetValue <LispPackage>("*PACKAGE*"); Assert.Equal("COMMON-LISP-USER", package.Name); host.Eval("(in-package \"TEST-PACKAGE\")"); package = host.GetValue <LispPackage>("*PACKAGE*"); Assert.Equal("TEST-PACKAGE", package.Name); }
public void CurrentPackageIsUpdatedWithInPackageFunctionWithKeyword() { var host = new LispHost(useInitScript: false); host.AddPackage("TEST-PACKAGE", new[] { host.CurrentPackage }); var package = host.GetValue <LispPackage>("*PACKAGE*"); Assert.Equal("COMMON-LISP", package.Name); host.Eval("(in-package :test-package)"); package = host.GetValue <LispPackage>("*PACKAGE*"); Assert.Equal("TEST-PACKAGE", package.Name); }
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); }
public void BindRestArgumentsInFunction() { var host = new LispHost(); host.Eval(@" (defun test (a b &rest the-rest) the-rest) (setf result-a (test 1 2) result-b (test 1 2 3)) "); var resultA = host.GetValue <LispList>("RESULT-A"); var resultB = host.GetValue <LispList>("RESULT-B"); Assert.True(resultA.IsNil()); Assert.Equal(1, resultB.Length); Assert.Equal(3, ((LispInteger)resultB.Value).Value); }
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); }
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); }
public void BindOptionalAndRestArguments() { var host = new LispHost(); host.Eval(@" (defun test (a &optional b &rest the-rest) (format nil ""~a:~a:~a"" a b the-rest)) (setf result-a (test 11) result-b (test 22 33) result-c (test 44 55 66)) "); var resultA = host.GetValue <LispString>("RESULT-A"); var resultB = host.GetValue <LispString>("RESULT-B"); var resultC = host.GetValue <LispString>("RESULT-C"); Assert.Equal("11:():()", resultA.Value); Assert.Equal("22:33:()", resultB.Value); Assert.Equal("44:55:(66)", resultC.Value); }
public void BindOptionalArgumentsInFunction() { var host = new LispHost(); host.Eval(@" (defun test (a &optional b (c 14)) (format nil ""~a:~a:~a"" a b c)) (setf result-a (test 11) result-b (test 22 33) result-c (test 44 55 66)) "); var resultA = host.GetValue <LispString>("RESULT-A"); var resultB = host.GetValue <LispString>("RESULT-B"); var resultC = host.GetValue <LispString>("RESULT-C"); Assert.Equal("11:():14", resultA.Value); Assert.Equal("22:33:14", resultB.Value); Assert.Equal("44:55:66", resultC.Value); }
public void LabelsFunctionDefinition() { var host = new LispHost(); var result = host.Eval(@" (labels ((increment-by-one (n) (+ n 1)) (increment-by-two (n) (increment-by-one (increment-by-one n))) ) (+ (increment-by-one 1) (increment-by-two 4)) ; (1 + 1) + (4 + 2) = 8 ) ").LastResult; Assert.Equal(new LispInteger(8), result); // ensure nothing leaked Assert.Null(host.GetValue("increment-by-one")); Assert.Null(host.GetValue("increment-by-two")); Assert.Null(host.GetValue("n")); }
public void WithOpenFile_Reading() { var output = new StringWriter(); var host = new LispHost(output: output); var result = host.Eval(@" (with-open-file (file-stream ""test-file.dat"") (format t ""read: ~S~%"" (read file-stream)) (format t ""evaluated: ~S~%"" (eval (read file-stream))) ) "); Assert.IsNotType <LispError>(result.LastResult); Assert.Equal("read: \"just a string\"\nevaluated: 5\n", NormalizeNewlines(output.ToString())); Assert.Null(host.GetValue("FILE-STREAM")); }
public void WithOpenFile_Writing() { var host = new LispHost(); using (var outputFile = new TemporaryFile(createFile: false)) { var result = host.Eval($@" (with-open-file (file-stream ""{outputFile.FilePath.Replace("\\", "\\\\")}"" :direction :output) (format file-stream ""wrote: ~S~%"" ""just-a-string"") (format file-stream ""wrote: ~S~%"" '(+ 2 3)) ) "); Assert.IsNotType <LispError>(result.LastResult); var actual = NormalizeNewlines(File.ReadAllText(outputFile.FilePath)); Assert.Equal("wrote: \"just-a-string\"\nwrote: (+ 2 3)\n", actual); Assert.Null(host.GetValue("FILE-STREAM")); } }