From 45a7a6b38bb3f22560bfb1adda8171c69f9cb529 Mon Sep 17 00:00:00 2001 From: Devin Bidwell Date: Fri, 19 Dec 2025 20:46:24 -0700 Subject: [PATCH 1/6] wip -- show ic10 alongside of Slang --- csharp_mod/Formatter.cs | 81 ++++++++++++++++++++++++++++++ csharp_mod/stationeersSlang.csproj | 4 ++ 2 files changed, 85 insertions(+) diff --git a/csharp_mod/Formatter.cs b/csharp_mod/Formatter.cs index 9ed20dd..1efae5f 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,17 @@ public class SlangFormatter : ICodeFormatter ); ApplyDiagnostics(dict); + + // If we have valid code, update the IC10 output + if ( + dict.Count < 1 + && Marshal.CompileFromString(inputSrc, out var compiled, out var sourceMap) + ) + { + ic10CompilationResult = compiled; + ic10SourceMap = sourceMap; + UpdateIc10Formatter(); + } } catch (OperationCanceledException) { } catch (Exception ex) @@ -134,6 +181,40 @@ 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; + } + + iC10CodeFormatter.Lines = new StyledText(); + + var minLine = lines.Min(map => map.Ic10Line); + var maxLine = lines.Max(map => map.Ic10Line); + + foreach (var line in lines) + { + iC10CodeFormatter + .Lines[(int)line.Ic10Line] + .ForEach(token => token.Style.Color = ColorIdentifier); + } + } + // This runs on the Main Thread private void ApplyDiagnostics(Dictionary> dict) { diff --git a/csharp_mod/stationeersSlang.csproj b/csharp_mod/stationeersSlang.csproj index 3e4c048..e8210ec 100644 --- a/csharp_mod/stationeersSlang.csproj +++ b/csharp_mod/stationeersSlang.csproj @@ -39,6 +39,10 @@ ./ref/Assembly-CSharp.dll False + + ./ref/RG.ImGui.dll + False + ./ref/IC10Editor.dll From 3f105ef35cb10d703562228ed1bb692e0122127e Mon Sep 17 00:00:00 2001 From: Devin Bidwell Date: Fri, 19 Dec 2025 21:08:19 -0700 Subject: [PATCH 2/6] update changelog and version bump --- Changelog.md | 6 ++++++ ModData/About/About.xml | 10 ++++------ csharp_mod/Plugin.cs | 2 +- csharp_mod/stationeersSlang.csproj | 2 +- rust_compiler/Cargo.toml | 2 +- 5 files changed, 13 insertions(+), 9 deletions(-) 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/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 e8210ec..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 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] From 1439f9ee7e65cb9b40571cd8dffbfa90914780bd Mon Sep 17 00:00:00 2001 From: Devin Bidwell Date: Fri, 19 Dec 2025 21:58:47 -0700 Subject: [PATCH 3/6] Remove conditional IC10 formatting --- csharp_mod/Formatter.cs | 35 ++++++++++++++++++----------------- rust_compiler/Cargo.lock | 2 +- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/csharp_mod/Formatter.cs b/csharp_mod/Formatter.cs index 1efae5f..55599c4 100644 --- a/csharp_mod/Formatter.cs +++ b/csharp_mod/Formatter.cs @@ -187,9 +187,12 @@ public class SlangFormatter : ICodeFormatter 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 - ); + var lines = ic10SourceMap + .FindAll(entry => + entry.SlangSource.StartLine == caretPos || entry.SlangSource.EndLine == caretPos + ) + .ConvertAll(el => el.Ic10Line) + .ToHashSet(); // 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 @@ -197,21 +200,19 @@ public class SlangFormatter : ICodeFormatter iC10CodeFormatter.ResetCode(ic10CompilationResult); - if (lines.Count < 1) + uint index = 0; + foreach (var line in iC10CodeFormatter.Lines) { - return; - } - - iC10CodeFormatter.Lines = new StyledText(); - - var minLine = lines.Min(map => map.Ic10Line); - var maxLine = lines.Max(map => map.Ic10Line); - - foreach (var line in lines) - { - iC10CodeFormatter - .Lines[(int)line.Ic10Line] - .ForEach(token => token.Style.Color = ColorIdentifier); + if (lines.Contains(index)) + { + index += 1; + continue; + } + line.ForEach(token => + { + token.Style.Color = ColorDefault; + }); + index += 1; } } 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", From 0962b3a5e7a49199b47eb57d190c2888b7c1fe4c Mon Sep 17 00:00:00 2001 From: Devin Bidwell Date: Sat, 20 Dec 2025 17:32:20 -0700 Subject: [PATCH 4/6] highlight background of IC10 for the current caret position of the Slang script --- csharp_mod/Formatter.cs | 74 +++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/csharp_mod/Formatter.cs b/csharp_mod/Formatter.cs index 55599c4..6d8bdbd 100644 --- a/csharp_mod/Formatter.cs +++ b/csharp_mod/Formatter.cs @@ -164,10 +164,25 @@ public class SlangFormatter : ICodeFormatter ApplyDiagnostics(dict); // If we have valid code, update the IC10 output - if ( - dict.Count < 1 - && Marshal.CompileFromString(inputSrc, out var compiled, out var sourceMap) - ) + 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; @@ -187,12 +202,11 @@ public class SlangFormatter : ICodeFormatter 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 - ) - .ConvertAll(el => el.Ic10Line) - .ToHashSet(); + var lines = ic10SourceMap.FindAll(entry => + entry.SlangSource.StartLine == caretPos || entry.SlangSource.EndLine == caretPos + ); + + lines.Sort((itemA, itemB) => itemA.Ic10Line.CompareTo(itemB.Ic10Line)); // 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 @@ -200,19 +214,35 @@ public class SlangFormatter : ICodeFormatter iC10CodeFormatter.ResetCode(ic10CompilationResult); - uint index = 0; - foreach (var line in iC10CodeFormatter.Lines) + if (lines.Count() < 1) { - if (lines.Contains(index)) - { - index += 1; - continue; - } - line.ForEach(token => - { - token.Style.Color = ColorDefault; - }); - index += 1; + return; + } + // get the "middle" IC10 line + var max = lines.Max(line => line.Ic10Line); + var min = lines.Min(line => line.Ic10Line); + var middle = (max + min) / 2; + + // first, update the line styles that are between min and max inclusive + 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; } } From f0e7506905322d3da8d6234d2d835e014b1a4ddf Mon Sep 17 00:00:00 2001 From: Devin Bidwell Date: Sat, 20 Dec 2025 17:35:22 -0700 Subject: [PATCH 5/6] Remove dead code and change some comments --- csharp_mod/Formatter.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/csharp_mod/Formatter.cs b/csharp_mod/Formatter.cs index 6d8bdbd..23831cc 100644 --- a/csharp_mod/Formatter.cs +++ b/csharp_mod/Formatter.cs @@ -218,12 +218,11 @@ public class SlangFormatter : ICodeFormatter { return; } - // get the "middle" IC10 line + // 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); - var middle = (max + min) / 2; - // first, update the line styles that are between min and max inclusive + // 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; From badcdd3c316592661b56809b47d4077346ca47d3 Mon Sep 17 00:00:00 2001 From: Devin Bidwell Date: Sat, 20 Dec 2025 17:47:35 -0700 Subject: [PATCH 6/6] Removed unneeded array sort --- csharp_mod/Formatter.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/csharp_mod/Formatter.cs b/csharp_mod/Formatter.cs index 23831cc..79cdbd8 100644 --- a/csharp_mod/Formatter.cs +++ b/csharp_mod/Formatter.cs @@ -206,8 +206,6 @@ public class SlangFormatter : ICodeFormatter entry.SlangSource.StartLine == caretPos || entry.SlangSource.EndLine == caretPos ); - lines.Sort((itemA, itemB) => itemA.Ic10Line.CompareTo(itemB.Ic10Line)); - // 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