From 353dc169446b9ad2c0210bbfc34a6acfadc5ba6f Mon Sep 17 00:00:00 2001 From: Devin Bidwell Date: Wed, 26 Nov 2025 16:02:00 -0700 Subject: [PATCH] Unified the C# mod and the Rust compiler into a monorepo --- .gitignore | 7 +- build.sh | 45 +++++-- csharp_mod/Patches.cs | 36 ++++++ csharp_mod/SlangPlugin.cs | 119 ++++++++++++++++++ csharp_mod/stationeersSlang.csproj | 57 +++++++++ Cargo.lock => rust_compiler/Cargo.lock | 0 Cargo.toml => rust_compiler/Cargo.toml | 0 .../libs}/compiler/Cargo.toml | 0 .../libs}/compiler/src/lib.rs | 0 .../compiler/src/test/binary_expression.rs | 0 .../libs}/compiler/src/test/branching.rs | 0 .../test/declaration_function_invocation.rs | 0 .../compiler/src/test/declaration_literal.rs | 0 .../compiler/src/test/function_declaration.rs | 0 .../compiler/src/test/logic_expression.rs | 0 .../libs}/compiler/src/test/loops.rs | 0 .../libs}/compiler/src/test/mod.rs | 0 .../libs}/compiler/src/test/syscall.rs | 0 .../libs}/compiler/src/v1.rs | 0 .../libs}/compiler/src/variable_manager.rs | 0 .../libs}/compiler/test_files/deviceIo.slang | 0 .../libs}/parser/Cargo.toml | 0 .../libs}/parser/src/lib.rs | 3 +- .../libs}/parser/src/sys_call.rs | 0 .../libs}/parser/src/test/blocks.rs | 0 .../libs}/parser/src/test/mod.rs | 0 .../libs}/parser/src/tree_node.rs | 0 .../libs}/tokenizer/Cargo.toml | 0 .../libs}/tokenizer/src/lib.rs | 0 .../libs}/tokenizer/src/token.rs | 0 .../libs}/tokenizer/tests/file.stlg | 0 .../rust-toolchain.toml | 0 {src => rust_compiler/src}/lib.rs | 0 {src => rust_compiler/src}/main.rs | 0 34 files changed, 253 insertions(+), 14 deletions(-) create mode 100644 csharp_mod/Patches.cs create mode 100644 csharp_mod/SlangPlugin.cs create mode 100644 csharp_mod/stationeersSlang.csproj rename Cargo.lock => rust_compiler/Cargo.lock (100%) rename Cargo.toml => rust_compiler/Cargo.toml (100%) rename {libs => rust_compiler/libs}/compiler/Cargo.toml (100%) rename {libs => rust_compiler/libs}/compiler/src/lib.rs (100%) rename {libs => rust_compiler/libs}/compiler/src/test/binary_expression.rs (100%) rename {libs => rust_compiler/libs}/compiler/src/test/branching.rs (100%) rename {libs => rust_compiler/libs}/compiler/src/test/declaration_function_invocation.rs (100%) rename {libs => rust_compiler/libs}/compiler/src/test/declaration_literal.rs (100%) rename {libs => rust_compiler/libs}/compiler/src/test/function_declaration.rs (100%) rename {libs => rust_compiler/libs}/compiler/src/test/logic_expression.rs (100%) rename {libs => rust_compiler/libs}/compiler/src/test/loops.rs (100%) rename {libs => rust_compiler/libs}/compiler/src/test/mod.rs (100%) rename {libs => rust_compiler/libs}/compiler/src/test/syscall.rs (100%) rename {libs => rust_compiler/libs}/compiler/src/v1.rs (100%) rename {libs => rust_compiler/libs}/compiler/src/variable_manager.rs (100%) rename {libs => rust_compiler/libs}/compiler/test_files/deviceIo.slang (100%) rename {libs => rust_compiler/libs}/parser/Cargo.toml (100%) rename {libs => rust_compiler/libs}/parser/src/lib.rs (99%) rename {libs => rust_compiler/libs}/parser/src/sys_call.rs (100%) rename {libs => rust_compiler/libs}/parser/src/test/blocks.rs (100%) rename {libs => rust_compiler/libs}/parser/src/test/mod.rs (100%) rename {libs => rust_compiler/libs}/parser/src/tree_node.rs (100%) rename {libs => rust_compiler/libs}/tokenizer/Cargo.toml (100%) rename {libs => rust_compiler/libs}/tokenizer/src/lib.rs (100%) rename {libs => rust_compiler/libs}/tokenizer/src/token.rs (100%) rename {libs => rust_compiler/libs}/tokenizer/tests/file.stlg (100%) rename rust-toolchain.toml => rust_compiler/rust-toolchain.toml (100%) rename {src => rust_compiler/src}/lib.rs (100%) rename {src => rust_compiler/src}/main.rs (100%) diff --git a/.gitignore b/.gitignore index b7c3df2..8764920 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ -/target -*.ic10 \ No newline at end of file +target +*.ic10 +release +bin +obj diff --git a/build.sh b/build.sh index 22273a4..436cfbd 100755 --- a/build.sh +++ b/build.sh @@ -2,21 +2,46 @@ set -e +RUST_DIR="rust_compiler" +CSHARP_DIR="csharp_mod" +RELEASE_DIR="release" + export RUSTFLAGS="--remap-path-prefix=${PWD}=. --remap-path-prefix=${HOME}/.cargo=~/.cargo" -# -- Build for Native (Linux x86-64) -- -echo "Building native (Linux x86-64) executable..." -cargo build --release --target=x86_64-unknown-linux-gnu -echo "Native build complete." echo "--------------------" +cd "$RUST_DIR" +echo "Building native Rust binaries and libs" + +# -- Build for Native (Linux x86-64) -- +cargo build --release --target=x86_64-unknown-linux-gnu # -- Build for Windows (x86-64) -- -echo "Building Windows (x86-64) dll and executable..." cargo build --release --target=x86_64-pc-windows-gnu -echo "Windows build successful." + +cd .. echo "--------------------" -echo "All builds successful" -echo "Linux executable at target/x86_64-unknown-linux-gnu/release/slang" -echo "Windows .exe at target/x86_64-pc-windows-gnu/release/slang.exe" -echo "Windows .dll at target/x86_64-pc-windows-gnu/release/slang.dll" +echo "Building C# mod" +echo "--------------------" + +cd "$CSHARP_DIR" +dotnet build -c Release + +cd .. +echo "--------------------" + +echo "Copying Release files to output directory" +echo "--------------------" + +RUST_WIN_EXE="$RUST_DIR/target/x86_64-pc-windows-gnu/release/slang.exe" +RUST_LINUX_BIN="$RUST_DIR/target/x86_64-unknown-linux-gnu/release/slang" +CHARP_DLL="$CSHARP_DIR/bin/Release/net46/StationeersSlang.dll" + +# Check if the release dir exists, if not: create it. +if [[ ! -d "$RELEASE_DIR" ]]; then + mkdir "$RELEASE_DIR" +fi + +cp "$RUST_WIN_EXE" "$RELEASE_DIR/slang.exe" +cp "$RUST_LINUX_BIN" "$RELEASE_DIR/slang" +cp "$CHARP_DLL" "$RELEASE_DIR/StationeersSlang.dll" diff --git a/csharp_mod/Patches.cs b/csharp_mod/Patches.cs new file mode 100644 index 0000000..3ea5f7f --- /dev/null +++ b/csharp_mod/Patches.cs @@ -0,0 +1,36 @@ +using Assets.Scripts.Objects.Motherboards; +using HarmonyLib; + +namespace Slang +{ + [HarmonyPatch] + public static class SlangPatches + { + [HarmonyPatch( + typeof(ProgrammableChipMotherboard), + nameof(ProgrammableChipMotherboard.InputFinished) + )] + [HarmonyPrefix] + public static void PGM_InputFinished(ref string result) + { + if (string.IsNullOrEmpty(result) || !SlangPlugin.IsSlangSource(ref result)) + { + return; + } + + L.Info("Detected Slang source, compiling..."); + + // Compile the Slang source into IC10 + string compiled = SlangPlugin.Compile(result); + + // Ensure that the string is correct + if (string.IsNullOrEmpty(compiled)) + { + return; + } + + // Set the result to be the compiled source so the rest of the function can continue as normal + result = compiled; + } + } +} diff --git a/csharp_mod/SlangPlugin.cs b/csharp_mod/SlangPlugin.cs new file mode 100644 index 0000000..9038960 --- /dev/null +++ b/csharp_mod/SlangPlugin.cs @@ -0,0 +1,119 @@ +using System; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using BepInEx; +using HarmonyLib; + +namespace Slang +{ + class L + { + private static BepInEx.Logging.ManualLogSource _logger; + + public static void SetLogger(BepInEx.Logging.ManualLogSource logger) + { + _logger = logger; + } + + public static void Debug(string message) + { + _logger.LogDebug(message); + } + + public static void Info(string message) + { + _logger.LogInfo(message); + } + + public static void Error(string message) + { + _logger.LogError(message); + } + + public static void Warning(string message) + { + _logger.LogWarning(message); + } + } + + [BepInPlugin(PluginGuid, PluginName, "0.1.0")] + public class SlangPlugin : BaseUnityPlugin + { + public const string PluginGuid = "com.dbidwell94.slang"; + public const string PluginName = "Slang"; + + const string RUST_DLL_NAME = "slang.dll"; + + private readonly string[] SLANG_KEYWORDS = { "let ", "fn " }; + + /// Takes raw `Slang` source code and compiles it into IC10 + [DllImport(RUST_DLL_NAME, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr compile_from_string(string input); + + /// Frees memory that was allocated by the FFI call to `compile_from_string` + [DllImport(RUST_DLL_NAME, CallingConvention = CallingConvention.Cdecl)] + private static extern void free_slang_string(IntPtr ptr); + + public static string Compile(string source) + { + if (string.IsNullOrEmpty(source)) + return ""; + + IntPtr ptr = compile_from_string(source); + try + { + return Marshal.PtrToStringAnsi(ptr); + } + finally + { + free_slang_string(ptr); + } + } + + public static bool IsSlangSource(ref string input) + { + return true; + } + + private void Awake() + { + L.SetLogger(Logger); + ExtractNativeDll(RUST_DLL_NAME); + var harmony = new Harmony("com.dbidwell94.slang"); + harmony.PatchAll(); + } + + private void ExtractNativeDll(string fileName) + { + string destinationPath = Path.Combine(Path.GetDirectoryName(Info.Location), fileName); + + Assembly assembly = Assembly.GetExecutingAssembly(); + + using (Stream stream = assembly.GetManifestResourceStream(fileName)) + { + if (stream == null) + { + Logger.LogError( + $"{RUST_DLL_NAME} compiler not found. This means it was not embedded in the mod. Please contact the mod author!" + ); + return; + } + + try + { + using (FileStream fileStream = new FileStream(destinationPath, FileMode.Create)) + { + stream.CopyTo(fileStream); + } + } + catch (IOException e) + { + Logger.LogWarning( + $"Could not overwrite {fileName} (it might be in use): {e.Message}" + ); + } + } + } + } +} diff --git a/csharp_mod/stationeersSlang.csproj b/csharp_mod/stationeersSlang.csproj new file mode 100644 index 0000000..20ec76f --- /dev/null +++ b/csharp_mod/stationeersSlang.csproj @@ -0,0 +1,57 @@ + + + + net46 + enable + StationeersSlang + Slang Compiler Bridge + 0.1.0 + true + latest + + + + /home/dbidwell/.local/share/Steam/steamapps/common/Stationeers/ + $(GameDir)/rocketstation_Data/Managed + $(GameDir)/BepInEx/core + + + + + $(ManagedDir)/netstandard.dll + False + + + $(BepInExDir)/BepInEx.dll + False + + + $(BepInExDir)/0Harmony.dll + False + + + + $(ManagedDir)/UnityEngine.dll + False + + + $(ManagedDir)/UnityEngine.CoreModule.dll + False + + + $(ManagedDir)/Assembly-CSharp.dll + False + + + $(ManagedDir)/Assembly-CSharp-firstpass.dll + False + + + + + + slang.dll + + + + diff --git a/Cargo.lock b/rust_compiler/Cargo.lock similarity index 100% rename from Cargo.lock rename to rust_compiler/Cargo.lock diff --git a/Cargo.toml b/rust_compiler/Cargo.toml similarity index 100% rename from Cargo.toml rename to rust_compiler/Cargo.toml diff --git a/libs/compiler/Cargo.toml b/rust_compiler/libs/compiler/Cargo.toml similarity index 100% rename from libs/compiler/Cargo.toml rename to rust_compiler/libs/compiler/Cargo.toml diff --git a/libs/compiler/src/lib.rs b/rust_compiler/libs/compiler/src/lib.rs similarity index 100% rename from libs/compiler/src/lib.rs rename to rust_compiler/libs/compiler/src/lib.rs diff --git a/libs/compiler/src/test/binary_expression.rs b/rust_compiler/libs/compiler/src/test/binary_expression.rs similarity index 100% rename from libs/compiler/src/test/binary_expression.rs rename to rust_compiler/libs/compiler/src/test/binary_expression.rs diff --git a/libs/compiler/src/test/branching.rs b/rust_compiler/libs/compiler/src/test/branching.rs similarity index 100% rename from libs/compiler/src/test/branching.rs rename to rust_compiler/libs/compiler/src/test/branching.rs diff --git a/libs/compiler/src/test/declaration_function_invocation.rs b/rust_compiler/libs/compiler/src/test/declaration_function_invocation.rs similarity index 100% rename from libs/compiler/src/test/declaration_function_invocation.rs rename to rust_compiler/libs/compiler/src/test/declaration_function_invocation.rs diff --git a/libs/compiler/src/test/declaration_literal.rs b/rust_compiler/libs/compiler/src/test/declaration_literal.rs similarity index 100% rename from libs/compiler/src/test/declaration_literal.rs rename to rust_compiler/libs/compiler/src/test/declaration_literal.rs diff --git a/libs/compiler/src/test/function_declaration.rs b/rust_compiler/libs/compiler/src/test/function_declaration.rs similarity index 100% rename from libs/compiler/src/test/function_declaration.rs rename to rust_compiler/libs/compiler/src/test/function_declaration.rs diff --git a/libs/compiler/src/test/logic_expression.rs b/rust_compiler/libs/compiler/src/test/logic_expression.rs similarity index 100% rename from libs/compiler/src/test/logic_expression.rs rename to rust_compiler/libs/compiler/src/test/logic_expression.rs diff --git a/libs/compiler/src/test/loops.rs b/rust_compiler/libs/compiler/src/test/loops.rs similarity index 100% rename from libs/compiler/src/test/loops.rs rename to rust_compiler/libs/compiler/src/test/loops.rs diff --git a/libs/compiler/src/test/mod.rs b/rust_compiler/libs/compiler/src/test/mod.rs similarity index 100% rename from libs/compiler/src/test/mod.rs rename to rust_compiler/libs/compiler/src/test/mod.rs diff --git a/libs/compiler/src/test/syscall.rs b/rust_compiler/libs/compiler/src/test/syscall.rs similarity index 100% rename from libs/compiler/src/test/syscall.rs rename to rust_compiler/libs/compiler/src/test/syscall.rs diff --git a/libs/compiler/src/v1.rs b/rust_compiler/libs/compiler/src/v1.rs similarity index 100% rename from libs/compiler/src/v1.rs rename to rust_compiler/libs/compiler/src/v1.rs diff --git a/libs/compiler/src/variable_manager.rs b/rust_compiler/libs/compiler/src/variable_manager.rs similarity index 100% rename from libs/compiler/src/variable_manager.rs rename to rust_compiler/libs/compiler/src/variable_manager.rs diff --git a/libs/compiler/test_files/deviceIo.slang b/rust_compiler/libs/compiler/test_files/deviceIo.slang similarity index 100% rename from libs/compiler/test_files/deviceIo.slang rename to rust_compiler/libs/compiler/test_files/deviceIo.slang diff --git a/libs/parser/Cargo.toml b/rust_compiler/libs/parser/Cargo.toml similarity index 100% rename from libs/parser/Cargo.toml rename to rust_compiler/libs/parser/Cargo.toml diff --git a/libs/parser/src/lib.rs b/rust_compiler/libs/parser/src/lib.rs similarity index 99% rename from libs/parser/src/lib.rs rename to rust_compiler/libs/parser/src/lib.rs index 8eca23a..481524b 100644 --- a/libs/parser/src/lib.rs +++ b/rust_compiler/libs/parser/src/lib.rs @@ -4,6 +4,7 @@ mod test; pub mod sys_call; pub mod tree_node; +use crate::sys_call::System; use quick_error::quick_error; use std::io::SeekFrom; use sys_call::SysCall; @@ -13,8 +14,6 @@ use tokenizer::{ }; use tree_node::*; -use crate::sys_call::System; - #[macro_export] /// A macro to create a boxed value. macro_rules! boxed { diff --git a/libs/parser/src/sys_call.rs b/rust_compiler/libs/parser/src/sys_call.rs similarity index 100% rename from libs/parser/src/sys_call.rs rename to rust_compiler/libs/parser/src/sys_call.rs diff --git a/libs/parser/src/test/blocks.rs b/rust_compiler/libs/parser/src/test/blocks.rs similarity index 100% rename from libs/parser/src/test/blocks.rs rename to rust_compiler/libs/parser/src/test/blocks.rs diff --git a/libs/parser/src/test/mod.rs b/rust_compiler/libs/parser/src/test/mod.rs similarity index 100% rename from libs/parser/src/test/mod.rs rename to rust_compiler/libs/parser/src/test/mod.rs diff --git a/libs/parser/src/tree_node.rs b/rust_compiler/libs/parser/src/tree_node.rs similarity index 100% rename from libs/parser/src/tree_node.rs rename to rust_compiler/libs/parser/src/tree_node.rs diff --git a/libs/tokenizer/Cargo.toml b/rust_compiler/libs/tokenizer/Cargo.toml similarity index 100% rename from libs/tokenizer/Cargo.toml rename to rust_compiler/libs/tokenizer/Cargo.toml diff --git a/libs/tokenizer/src/lib.rs b/rust_compiler/libs/tokenizer/src/lib.rs similarity index 100% rename from libs/tokenizer/src/lib.rs rename to rust_compiler/libs/tokenizer/src/lib.rs diff --git a/libs/tokenizer/src/token.rs b/rust_compiler/libs/tokenizer/src/token.rs similarity index 100% rename from libs/tokenizer/src/token.rs rename to rust_compiler/libs/tokenizer/src/token.rs diff --git a/libs/tokenizer/tests/file.stlg b/rust_compiler/libs/tokenizer/tests/file.stlg similarity index 100% rename from libs/tokenizer/tests/file.stlg rename to rust_compiler/libs/tokenizer/tests/file.stlg diff --git a/rust-toolchain.toml b/rust_compiler/rust-toolchain.toml similarity index 100% rename from rust-toolchain.toml rename to rust_compiler/rust-toolchain.toml diff --git a/src/lib.rs b/rust_compiler/src/lib.rs similarity index 100% rename from src/lib.rs rename to rust_compiler/src/lib.rs diff --git a/src/main.rs b/rust_compiler/src/main.rs similarity index 100% rename from src/main.rs rename to rust_compiler/src/main.rs