Skip to content

Commit

Permalink
add NoReaderMacros parsing mode for speed
Browse files Browse the repository at this point in the history
  • Loading branch information
brettfo committed Jun 20, 2024
1 parent 51a122f commit c32b3b5
Show file tree
Hide file tree
Showing 12 changed files with 333 additions and 35 deletions.
6 changes: 4 additions & 2 deletions src/IxMilia.Lisp.LanguageServer/LanguageServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ public class LanguageServer
{
private JsonRpc _rpc;
private Dictionary<string, (LispHost Host, string Content, ResettableTextWriter TextWriter)> _documentContents = new Dictionary<string, (LispHost, string, ResettableTextWriter)>();
private LispReaderType _defaultReaderType;

public LanguageServer(Stream sendingStream, Stream receivingStream)
public LanguageServer(Stream sendingStream, Stream receivingStream, LispReaderType defaultReaderType = LispReaderType.Compiled)
{
var messageHandler = CreateMessageHandler(sendingStream, receivingStream);
_rpc = new JsonRpc(messageHandler, this);
_rpc.TraceSource = new TraceSource("debugging-trace-listener", SourceLevels.All);
_rpc.TraceSource.Listeners.Add(new DebuggingTraceListener());
_defaultReaderType = defaultReaderType;
}

internal static IJsonRpcMessageHandler CreateMessageHandler(Stream sendingStream, Stream receivingStream)
Expand Down Expand Up @@ -65,7 +67,7 @@ private async Task SetDocumentContentsAsync(string uri, string newContent, Cance
else
{
var output = new ResettableTextWriter();
var configuration = new LispHostConfiguration(output: output);
var configuration = new LispHostConfiguration(output: output, readerType: _defaultReaderType);
host = await LispHost.CreateAsync(configuration);
textWriter = output;
}
Expand Down
12 changes: 8 additions & 4 deletions src/IxMilia.Lisp.Test/EndToEndTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,23 @@ private string GetFileContents(string fileName)
return fileContents;
}

private async Task EvalFile(string fileName)
private async Task EvalFile(string fileName, LispReaderType readerType)
{
var contents = GetFileContents(fileName);
var host = await CreateHostAsync();
host.SetReaderFunction(readerType);
var executionState = LispExecutionState.CreateExecutionState(host.RootFrame, allowHalting: false);
var result = await host.EvalAsync(fileName, contents, executionState);
Assert.True(result.Value.Equals(host.T), result.Value.ToString());
}

[Fact]
public async Task Runtime()
[Theory]
//[InlineData(LispReaderType.Interpreted)] // skip for now
[InlineData(LispReaderType.Compiled)]
[InlineData(LispReaderType.NoReaderMacros)]
public async Task Runtime(LispReaderType readerType)
{
await EvalFile("runtime-tests.lisp");
await EvalFile("runtime-tests.lisp", readerType);
}
}
}
20 changes: 11 additions & 9 deletions src/IxMilia.Lisp.Test/ObjectReadTestsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public abstract class ObjectReadTestsBase : TestBase
return (host, evalResult.Value);
}

private async Task<LispObject> ReadAsync(string code, bool checkForErrors = true)
protected async Task<LispObject> ReadAsync(string code, bool checkForErrors = true)
{
var (_host, result) = await ReadHostAndResultAsync(code, checkForErrors);
return result;
Expand Down Expand Up @@ -461,14 +461,16 @@ public async Task ReadTableCopying()
}

[Theory]
[InlineData("`(1 ,(+ 2 3) (b))", "(CONS (QUOTE 1) (CONS (QUOTE 5) (CONS (CONS (QUOTE B) ()) ())))")]
[InlineData("`,(+ 1 2)", "(QUOTE 3)")]
[InlineData("`#(1 2 ,(+ 1 2) ,#(4))", "(QUOTE #(1 2 3 #(4)))")]
[InlineData("`a", "(QUOTE A)")]
public async Task BackQuoteRead(string code, string expected)
{
var (host, result) = await ReadHostAndResultAsync(code);
Assert.Equal(expected, result.ToDisplayString(host.CurrentPackage));
[InlineData("`(1 ,(+ 2 3) (b))", "(1 5 (B))")]
[InlineData("`,(+ 1 2)", "3")]
[InlineData("`#(1 2 ,(+ 1 2) ,#(4))", "#(1 2 3 #(4))", "(APPLY #'VECTOR (QUOTE (1 2 3 #(4))))")]
[InlineData("`a", "A")]
public async Task BackQuoteReadAndEval(string code, string expected, string alternateExpected = null)
{
var (host, readResult) = await ReadHostAndResultAsync(code);
var evalResult = host.EvalAsync(readResult, host.CreateExecutionState());
var actual = evalResult.Result.Value.ToDisplayString(host.CurrentPackage);
Assert.True(expected == actual || alternateExpected == actual, $"Expected: {expected} or {alternateExpected}, Actual: {actual}");
}

[Fact]
Expand Down
7 changes: 7 additions & 0 deletions src/IxMilia.Lisp.Test/ObjectReadTests_NoReaderMacros.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace IxMilia.Lisp.Test
{
public class ObjectReadTests_NoReaderMacros: ObjectReadTestsBase
{
public override LispReaderType ReaderType => LispReaderType.NoReaderMacros;
}
}
47 changes: 47 additions & 0 deletions src/IxMilia.Lisp.Test/TimingTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Xunit;

namespace IxMilia.Lisp.Test
{
public class TimingTests : TestBase
{
[Fact]
public async Task ReadCodeAsync()
{
var assemblyDirectory = Path.GetDirectoryName(GetType().Assembly.Location);
var fullFilePath = Path.Combine(assemblyDirectory, "runtime-tests.lisp");
var fileContents = File.ReadAllText(fullFilePath);
var code = "(progn\n" + fileContents + "\n)\n";
var results = new StringBuilder();
foreach (var readerType in new[] { LispReaderType.Compiled, LispReaderType.NoReaderMacros })
{
var host = await CreateHostAsync();
host.SetReaderFunction(readerType);

for (int i = 0; i < 2; i++)
{
var executionState = host.CreateExecutionState();
var reader = new StringReader(code);
var stream = new LispTextStream("TEST-INPUT", reader, TextWriter.Null);
var obj = LispList.FromItems(new LispUnresolvedSymbol("READ"), stream);
var sw = new Stopwatch();
sw.Start();
var evalResult = await host.EvalAsync(obj, executionState);
sw.Stop();
EnsureNotError(evalResult.Value);

if (i == 1)
{
results.AppendLine($"{readerType}: {sw.ElapsedMilliseconds}ms");
}
}
}

// uncomment to see timings
//Assert.Fail(results.ToString());
}
}
}
2 changes: 1 addition & 1 deletion src/IxMilia.Lisp.Wasm/LispAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class LispAdapter
[JSInvokable]
public async Task InitAsync(string code)
{
_languageServer = new LS.LanguageServer(new MemoryStream(), new MemoryStream());
_languageServer = new LS.LanguageServer(new MemoryStream(), new MemoryStream(), LispReaderType.NoReaderMacros);
_languageServer.Initialize(new InitializeParams(0, Array.Empty<WorkspaceFolder>()));
await _languageServer.TextDocumentDidOpenAsync(new DidOpenTextDocumentParams(new TextDocumentItem(ReplUri, "lisp", 0, code)));
}
Expand Down
1 change: 1 addition & 0 deletions src/IxMilia.Lisp.Wasm/wwwroot/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<button id="eval-button">Eval</button>
<textarea id="output"></textarea>
<button id="clear-button">Clear</button>
<div id="time-status"></div>
<script src="_framework/blazor.webassembly.js"></script>
<script src="app.bundle.js"></script>
</body>
Expand Down
Loading

0 comments on commit c32b3b5

Please sign in to comment.