diff --git a/Changelog.md b/Changelog.md index 59ede2b..e5edd08 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,11 @@ # Changelog +[0.4.0] + +- First pass getting compiled IC10 to output along side the Slang source code + - IC10 side is currently not scrollable, and text might be cut off from the bottom, + requiring newlines to be added to the bottom of the Slang source if needed + [0.3.4] - Added support for `loadReagent`, which maps to the `lr` IC10 instruction diff --git a/ModData/About/About.xml b/ModData/About/About.xml index 5e0bd4d..a9e948d 100644 --- a/ModData/About/About.xml +++ b/ModData/About/About.xml @@ -2,7 +2,7 @@ Slang JoeDiertay - 0.3.4 + 0.4.0 [h1]Slang: High-Level Programming for Stationeers[/h1] @@ -23,6 +23,8 @@ Slang (Stationeers Language) brings modern programming to Stationeers. It allows [*] [b]Optimizations:[/b] Features like Constant Folding calculate math at compile time to save instructions. [*] [b]Device Aliasing:[/b] Simple mapping: device sensor = "d0". [*] [b]Temperature Literals:[/b] Don't worry about converting Celsius to Kelvin anymore. Define your temperatures as whatever you want and append the proper suffix at the end (ex. 20c, 68f, 293.15k) +[*] [b]Side-by-side IC10 output:[/b] Preview the compiled IC10 alongside the Slang source code. What you see is what you get. +[*] [b]Compiler Optimizations:[/b] Slang now does its best to safely optimize the output IC10, removing labels, unnecessary moves, etc. [/list] [h2]Installation[/h2] @@ -50,16 +52,12 @@ loop { [h2]Known Issues (Beta)[/h2] [list] -[*] [b]Code Size:[/b] Compiled output is currently more verbose than hand-optimized assembly. Optimization passes are planned. -[*] [b]Stack Access:[/b] Direct stack memory access is disabled to prevent conflicts with the compiler's internal memory management. +[*] [b]Stack Access:[/b] Direct stack memory access is disabled to prevent conflicts with the compiler's internal memory management. A workaround is being planned. [*] [b]Documentation:[/b] In-game tooltips for syscalls (like load, set) are WIP. Check the "Slang" entry in the Stationpedia (F1) for help. -[*] [b]Debugging:[/b] Runtime errors currently point to the compiled IC10 line number, not your Slang source line. Source mapping is coming soon. [/list] [h2]Planned Features[/h2] [list] -[*] Side-by-side view: Slang vs. Compiled IC10. -[*] Compiler optimizations (dead code elimination, smarter register allocation). [*] Enhanced LSP features (Autocomplete, Go to Definition). [*] Full feature parity with all IC10 instructions. [*] Tutorials and beginner script examples. diff --git a/csharp_mod/Formatter.cs b/csharp_mod/Formatter.cs index 9ed20dd..79cdbd8 100644 --- a/csharp_mod/Formatter.cs +++ b/csharp_mod/Formatter.cs @@ -5,13 +5,20 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using ImGuiNET; using StationeersIC10Editor; +using StationeersIC10Editor.IC10; +using UnityEngine; public class SlangFormatter : ICodeFormatter { private CancellationTokenSource? _lspCancellationToken; private object _tokenLock = new(); + private IC10CodeFormatter iC10CodeFormatter = new IC10CodeFormatter(); + private string ic10CompilationResult = ""; + private List ic10SourceMap = new(); + // VS Code Dark Theme Palette public static readonly uint ColorControl = ColorFromHTML("#C586C0"); // Pink (if, return, loop) public static readonly uint ColorDeclaration = ColorFromHTML("#569CD6"); // Blue (let, device, fn) @@ -33,6 +40,7 @@ public class SlangFormatter : ICodeFormatter : base() { OnCodeChanged += HandleCodeChanged; + OnCaretMoved += UpdateIc10Formatter; } public static double MatchingScore(string input) @@ -70,6 +78,34 @@ public class SlangFormatter : ICodeFormatter return this.Lines.RawText; } + public override void DrawLine(int lineIndex, TextRange selection, bool drawLineNumber = true) + { + Vector2 cursorPos = ImGui.GetCursorScreenPos(); + Vector2 space = ImGui.GetContentRegionAvail(); + base.DrawLine(lineIndex, selection, drawLineNumber); + + var charWidth = Settings.CharWidth; + + var width = Mathf.Max(Lines.Width + 10.0f + LineNumberOffset * charWidth, space.x / 2); + + ImGui + .GetWindowDrawList() + .AddLine( + new Vector2(cursorPos.x + width + 4.5f * charWidth, cursorPos.y), + new Vector2( + cursorPos.x + width + 4.5f * charWidth, + cursorPos.y + space.y + Settings.LineHeight + ), + ColorLineNumber, + 1.0f + ); + + cursorPos.x += width; + ImGui.SetCursorScreenPos(cursorPos); + if (lineIndex < iC10CodeFormatter.Lines.Count) + iC10CodeFormatter.DrawLine(lineIndex, new TextRange(), true); + } + public override StyledLine ParseLine(string line) { // We create the line first @@ -126,6 +162,32 @@ public class SlangFormatter : ICodeFormatter ); ApplyDiagnostics(dict); + + // If we have valid code, update the IC10 output + if (dict.Count > 0) + { + return; + } + + var (compilationSuccess, compiled, sourceMap) = await Task.Run( + () => + { + var successful = Marshal.CompileFromString( + inputSrc, + out var compiled, + out var sourceMap + ); + return (successful, compiled, sourceMap); + }, + cancellationToken + ); + + if (compilationSuccess) + { + ic10CompilationResult = compiled; + ic10SourceMap = sourceMap; + UpdateIc10Formatter(); + } } catch (OperationCanceledException) { } catch (Exception ex) @@ -134,6 +196,53 @@ public class SlangFormatter : ICodeFormatter } } + private void UpdateIc10Formatter() + { + iC10CodeFormatter.Editor = Editor; + var caretPos = Editor.CaretPos.Line; + + // get the slang sourceMap at the current editor line + var lines = ic10SourceMap.FindAll(entry => + entry.SlangSource.StartLine == caretPos || entry.SlangSource.EndLine == caretPos + ); + + // extract the current "context" of the ic10 compilation. The current Slang source line + // should be directly next to the compiled IC10 source line, and we should highlight the + // IC10 code that directly represents the Slang source + + iC10CodeFormatter.ResetCode(ic10CompilationResult); + + if (lines.Count() < 1) + { + return; + } + // get the total range of the IC10 source for the selected Slang line + var max = lines.Max(line => line.Ic10Line); + var min = lines.Min(line => line.Ic10Line); + + // highlight all the IC10 lines that are within the specified range + foreach (var index in Enumerable.Range((int)min, (int)(max - min) + 1)) + { + var lineText = iC10CodeFormatter.Lines[index].Text; + + var newLine = new StyledLine( + lineText, + [ + new SemanticToken + { + Column = 0, + Length = lineText.Length, + Line = index, + Background = ColorIdentifier, + Color = ColorFromHTML("black"), + }, + ] + ); + + iC10CodeFormatter.Lines[index] = newLine; + } + } + // This runs on the Main Thread private void ApplyDiagnostics(Dictionary> dict) { diff --git a/csharp_mod/Plugin.cs b/csharp_mod/Plugin.cs index 75ed957..d33b721 100644 --- a/csharp_mod/Plugin.cs +++ b/csharp_mod/Plugin.cs @@ -41,7 +41,7 @@ namespace Slang { public const string PluginGuid = "com.biddydev.slang"; public const string PluginName = "Slang"; - public const string PluginVersion = "0.3.4"; + public const string PluginVersion = "0.4.0"; public static Mod MOD = new Mod(PluginName, PluginVersion); diff --git a/csharp_mod/stationeersSlang.csproj b/csharp_mod/stationeersSlang.csproj index 3e4c048..e7aba92 100644 --- a/csharp_mod/stationeersSlang.csproj +++ b/csharp_mod/stationeersSlang.csproj @@ -5,7 +5,7 @@ enable StationeersSlang Slang Compiler Bridge - 0.3.2 + 0.4.0 true latest @@ -39,6 +39,10 @@ ./ref/Assembly-CSharp.dll False + + ./ref/RG.ImGui.dll + False + ./ref/IC10Editor.dll diff --git a/rust_compiler/Cargo.lock b/rust_compiler/Cargo.lock index 4a2af3c..b13e2ce 100644 --- a/rust_compiler/Cargo.lock +++ b/rust_compiler/Cargo.lock @@ -930,7 +930,7 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "slang" -version = "0.3.4" +version = "0.4.0" dependencies = [ "anyhow", "clap", diff --git a/rust_compiler/Cargo.toml b/rust_compiler/Cargo.toml index 4bdc1b7..ac41a84 100644 --- a/rust_compiler/Cargo.toml +++ b/rust_compiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "slang" -version = "0.3.4" +version = "0.4.0" edition = "2021" [workspace]