From 06bc2efe2bc4a14c1d89f3007e4f2033646a95d2 Mon Sep 17 00:00:00 2001 From: kalimag Date: Sat, 7 Sep 2024 03:32:21 +0200 Subject: [PATCH 1/6] Improve Lua REPL handling of statements Stop printing syntax error messages when executing variable assignments etc. --- .../lua/ILuaLibraries.cs | 2 +- .../tools/Lua/LuaConsole.cs | 18 +++++------ .../tools/Lua/LuaLibraries.cs | 31 +++++++++++++++++-- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/BizHawk.Client.Common/lua/ILuaLibraries.cs b/src/BizHawk.Client.Common/lua/ILuaLibraries.cs index c4e1ea10789..dd66772f02b 100644 --- a/src/BizHawk.Client.Common/lua/ILuaLibraries.cs +++ b/src/BizHawk.Client.Common/lua/ILuaLibraries.cs @@ -51,7 +51,7 @@ INamedLuaFunction CreateAndRegisterNamedFunction( void SpawnAndSetFileThread(string pathToLoad, LuaFile lf); - void ExecuteString(string command); + object[] ExecuteString(string command); (bool WaitForFrame, bool Terminated) ResumeScript(LuaFile lf); } diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs index 5ed96ca6669..8cda0fbaa5b 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs @@ -1388,18 +1388,14 @@ private void InputBox_KeyDown(object sender, KeyEventArgs e) LuaSandbox.Sandbox(null, () => { - LuaImp.ExecuteString($"console.log({rawCommand})"); - }, () => - { - LuaSandbox.Sandbox(null, () => + var results = LuaImp.ExecuteString(rawCommand); + // empty array if the command was e.g. a variable assignment or a loop without return statement + // "void" functions return a single null + // if output didn't change, Print will take care of writing out "(no return)" + if (results is not [ ] and not [ null ] || OutputBox.Text == consoleBeforeCall) { - LuaImp.ExecuteString(rawCommand); - - if (OutputBox.Text == consoleBeforeCall) - { - WriteLine("Command successfully executed"); - } - }); + LuaLibraries.Print(results); + } }); _messageCount = 0; diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs index 0490799b8f8..002d04d9cae 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs @@ -323,8 +323,35 @@ public LuaThread SpawnCoroutine(string file) public void SpawnAndSetFileThread(string pathToLoad, LuaFile lf) => lf.Thread = SpawnCoroutine(pathToLoad); - public void ExecuteString(string command) - => _lua.DoString(command); + /// + /// Executes Lua code. Automatically prepends statement if possible. + /// + /// + /// Values returned by the Lua script, if any. + /// + public object[] ExecuteString(string command) + { + const string ChunkName = "input"; // shows up in error messages + + // Use LoadString to separate parsing and execution, to tell syntax errors and runtime errors apart + LuaFunction func; + try + { + // Adding a return is necessary to get out return values of functions and turn expressions ("1+1" etc.) into valid statements + func = _lua.LoadString($"return {command}", ChunkName); + } + catch (Exception) + { + // command may be a valid statement without the added "return" + // if previous attempt couldn't be parsed, run the raw command + return _lua.DoString(command, ChunkName); + } + + using (func) + { + return func.Call(); + } + } public (bool WaitForFrame, bool Terminated) ResumeScript(LuaFile lf) { From 5663db1d2e1674fe7b9a7bf5165671218db378d8 Mon Sep 17 00:00:00 2001 From: kalimag Date: Wed, 20 Nov 2024 15:13:20 +0100 Subject: [PATCH 2/6] Move doc comments to interface --- src/BizHawk.Client.Common/lua/ILuaLibraries.cs | 6 ++++++ src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/BizHawk.Client.Common/lua/ILuaLibraries.cs b/src/BizHawk.Client.Common/lua/ILuaLibraries.cs index dd66772f02b..ca3f164c619 100644 --- a/src/BizHawk.Client.Common/lua/ILuaLibraries.cs +++ b/src/BizHawk.Client.Common/lua/ILuaLibraries.cs @@ -51,6 +51,12 @@ INamedLuaFunction CreateAndRegisterNamedFunction( void SpawnAndSetFileThread(string pathToLoad, LuaFile lf); + /// + /// Executes Lua code. Automatically prepends statement if possible. + /// + /// + /// Values returned by the Lua script, if any. + /// object[] ExecuteString(string command); (bool WaitForFrame, bool Terminated) ResumeScript(LuaFile lf); diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs index 002d04d9cae..e77c0d912a0 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaLibraries.cs @@ -323,12 +323,6 @@ public LuaThread SpawnCoroutine(string file) public void SpawnAndSetFileThread(string pathToLoad, LuaFile lf) => lf.Thread = SpawnCoroutine(pathToLoad); - /// - /// Executes Lua code. Automatically prepends statement if possible. - /// - /// - /// Values returned by the Lua script, if any. - /// public object[] ExecuteString(string command) { const string ChunkName = "input"; // shows up in error messages From e242052bfa8898eed6a646edccae5463bc7d1cdc Mon Sep 17 00:00:00 2001 From: kalimag Date: Wed, 20 Nov 2024 15:14:35 +0100 Subject: [PATCH 3/6] Simplify pattern matching expression --- src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs index 8cda0fbaa5b..4dcca5ababc 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs @@ -1392,7 +1392,7 @@ private void InputBox_KeyDown(object sender, KeyEventArgs e) // empty array if the command was e.g. a variable assignment or a loop without return statement // "void" functions return a single null // if output didn't change, Print will take care of writing out "(no return)" - if (results is not [ ] and not [ null ] || OutputBox.Text == consoleBeforeCall) + if (results is not ([ ] or [ null ]) || OutputBox.Text == consoleBeforeCall) { LuaLibraries.Print(results); } From 875bc3c41e147a5485d71346ed4282ca729d38d7 Mon Sep 17 00:00:00 2001 From: kalimag Date: Wed, 20 Nov 2024 15:30:42 +0100 Subject: [PATCH 4/6] Use reference equality to test for console output --- src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs index 4dcca5ababc..7628693f086 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs @@ -1392,7 +1392,7 @@ private void InputBox_KeyDown(object sender, KeyEventArgs e) // empty array if the command was e.g. a variable assignment or a loop without return statement // "void" functions return a single null // if output didn't change, Print will take care of writing out "(no return)" - if (results is not ([ ] or [ null ]) || OutputBox.Text == consoleBeforeCall) + if (results is not ([ ] or [ null ]) || ReferenceEquals(OutputBox.Text, consoleBeforeCall)) { LuaLibraries.Print(results); } From fd483cef4c2f50129c54657d465bfb08c269fafa Mon Sep 17 00:00:00 2001 From: kalimag Date: Thu, 21 Nov 2024 00:08:40 +0100 Subject: [PATCH 5/6] Revert "Use reference equality to test for console output" This reverts commit 875bc3c41e147a5485d71346ed4282ca729d38d7. --- src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs index 7628693f086..4dcca5ababc 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs @@ -1392,7 +1392,7 @@ private void InputBox_KeyDown(object sender, KeyEventArgs e) // empty array if the command was e.g. a variable assignment or a loop without return statement // "void" functions return a single null // if output didn't change, Print will take care of writing out "(no return)" - if (results is not ([ ] or [ null ]) || ReferenceEquals(OutputBox.Text, consoleBeforeCall)) + if (results is not ([ ] or [ null ]) || OutputBox.Text == consoleBeforeCall) { LuaLibraries.Print(results); } From cb3505b6de374707759164b27b722b6c81bd9ed2 Mon Sep 17 00:00:00 2001 From: kalimag Date: Thu, 21 Nov 2024 00:38:09 +0100 Subject: [PATCH 6/6] Use `_messageCount` to test for console output --- src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs index 4dcca5ababc..ed690cfc1c9 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs @@ -1373,7 +1373,6 @@ private void InputBox_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { - string consoleBeforeCall = OutputBox.Text; var rawCommand = InputBox.Text; InputBox.Clear(); InputBox.Refresh(); // if the command is something like `client.seekframe`, the Lua Console (and MainForm) will freeze until it finishes, so at least make it obvious that the Enter press was received @@ -1388,11 +1387,12 @@ private void InputBox_KeyDown(object sender, KeyEventArgs e) LuaSandbox.Sandbox(null, () => { + var prevMessageCount = _messageCount; var results = LuaImp.ExecuteString(rawCommand); // empty array if the command was e.g. a variable assignment or a loop without return statement // "void" functions return a single null // if output didn't change, Print will take care of writing out "(no return)" - if (results is not ([ ] or [ null ]) || OutputBox.Text == consoleBeforeCall) + if (results is not ([ ] or [ null ]) || _messageCount == prevMessageCount) { LuaLibraries.Print(results); }