From 1b8a52035880b6af2aeb3b2d62b0dbff18cf33fd Mon Sep 17 00:00:00 2001
From: gpwclark <gpwclark@gmail.com>
Date: Sun, 26 Jan 2025 11:26:48 -0500
Subject: [PATCH] trying to auto generate a page that will report what
 functions need to be implemented or not...

---
 Cargo.lock                                    |   1 +
 doc/mdbook-slosh-eval/Cargo.lock              |  35 ++++--
 doc/mdbook-slosh-eval/Cargo.toml              |   1 +
 doc/mdbook-slosh-eval/src/main.rs             |  10 +-
 doc/mk-site.sh                                |   2 +
 doc/src/SUMMARY.md                            |   1 +
 doc/src/transition-from-legacy.md             |  10 ++
 slosh_test/Cargo.toml                         |   1 +
 slosh_test/src/main.rs                        |   6 +-
 slosh_test_lib/README.md                      |   3 +
 slosh_test_lib/build.rs                       | 105 ++++++++++++++++++
 slosh_test_lib/run-tests.slosh                |  28 +++++
 {slosh_test => slosh_test_lib}/src/docs.rs    |   0
 .../src/docs/legacy.rs                        |   0
 slosh_test_lib/src/lib.rs                     |   1 +
 slosh_test_lib/tests/slosh-tests.rs           |  50 +++++++++
 16 files changed, 239 insertions(+), 15 deletions(-)
 create mode 100644 doc/src/transition-from-legacy.md
 create mode 100644 slosh_test_lib/README.md
 create mode 100644 slosh_test_lib/build.rs
 create mode 100755 slosh_test_lib/run-tests.slosh
 rename {slosh_test => slosh_test_lib}/src/docs.rs (100%)
 rename {slosh_test => slosh_test_lib}/src/docs/legacy.rs (100%)
 create mode 100644 slosh_test_lib/src/lib.rs
 create mode 100644 slosh_test_lib/tests/slosh-tests.rs

diff --git a/Cargo.lock b/Cargo.lock
index 69a0e7a9f5..aeb6072751 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2192,6 +2192,7 @@ dependencies = [
  "shell",
  "sl-compiler",
  "slosh_lib",
+ "slosh_test_lib",
  "slvm",
  "temp-env",
  "tempfile",
diff --git a/doc/mdbook-slosh-eval/Cargo.lock b/doc/mdbook-slosh-eval/Cargo.lock
index e2ca2ae771..3a502a6b3a 100644
--- a/doc/mdbook-slosh-eval/Cargo.lock
+++ b/doc/mdbook-slosh-eval/Cargo.lock
@@ -158,7 +158,7 @@ dependencies = [
 
 [[package]]
 name = "bridge_adapters"
-version = "0.1.0"
+version = "0.11.0"
 dependencies = [
  "bridge_types",
  "compile_state",
@@ -167,7 +167,7 @@ dependencies = [
 
 [[package]]
 name = "bridge_macros"
-version = "0.1.0"
+version = "0.11.0"
 dependencies = [
  "bridge_types",
  "quote",
@@ -178,7 +178,7 @@ dependencies = [
 
 [[package]]
 name = "bridge_types"
-version = "0.1.0"
+version = "0.11.0"
 
 [[package]]
 name = "bstr"
@@ -193,7 +193,7 @@ dependencies = [
 
 [[package]]
 name = "builtins"
-version = "0.1.0"
+version = "0.11.0"
 dependencies = [
  "bridge_adapters",
  "bridge_macros",
@@ -312,7 +312,7 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
 
 [[package]]
 name = "compile_state"
-version = "0.1.0"
+version = "0.11.0"
 dependencies = [
  "slvm",
 ]
@@ -994,6 +994,7 @@ dependencies = [
  "semver",
  "serde_json",
  "slosh_lib",
+ "slosh_test_lib",
  "toml",
 ]
 
@@ -1577,7 +1578,7 @@ dependencies = [
 
 [[package]]
 name = "shell"
-version = "0.1.0"
+version = "0.11.0"
 dependencies = [
  "cfg-if",
  "chrono",
@@ -1600,7 +1601,7 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
 
 [[package]]
 name = "sl-compiler"
-version = "0.1.0"
+version = "0.11.0"
 dependencies = [
  "chrono",
  "compile_state",
@@ -1646,7 +1647,7 @@ dependencies = [
 
 [[package]]
 name = "slosh_lib"
-version = "0.10.0"
+version = "0.11.0"
 dependencies = [
  "bridge_adapters",
  "builtins",
@@ -1661,9 +1662,25 @@ dependencies = [
  "unicode_reader",
 ]
 
+[[package]]
+name = "slosh_test_lib"
+version = "0.11.0"
+dependencies = [
+ "bridge_adapters",
+ "chrono",
+ "compile_state",
+ "lazy_static",
+ "mdbook",
+ "regex",
+ "shell",
+ "sl-compiler",
+ "slosh_lib",
+ "slvm",
+]
+
 [[package]]
 name = "slvm"
-version = "0.1.0"
+version = "0.11.0"
 dependencies = [
  "bridge_types",
  "unicode-segmentation",
diff --git a/doc/mdbook-slosh-eval/Cargo.toml b/doc/mdbook-slosh-eval/Cargo.toml
index 95e13057f3..fc067d3ca5 100644
--- a/doc/mdbook-slosh-eval/Cargo.toml
+++ b/doc/mdbook-slosh-eval/Cargo.toml
@@ -15,6 +15,7 @@ log = "*"
 pulldown-cmark = "0.10.2"
 pulldown-cmark-to-cmark = "13.0.0"
 slosh_lib = { path = "../../slosh_lib" }
+slosh_test_lib = { path = "../../slosh_test_lib" }
 toml = "*"
 
 [workspace]
diff --git a/doc/mdbook-slosh-eval/src/main.rs b/doc/mdbook-slosh-eval/src/main.rs
index a1fff02126..8cc68f465e 100644
--- a/doc/mdbook-slosh-eval/src/main.rs
+++ b/doc/mdbook-slosh-eval/src/main.rs
@@ -2,6 +2,7 @@ extern crate pulldown_cmark;
 extern crate pulldown_cmark_to_cmark;
 
 use crate::slosh_eval_lib::EvalSlosh;
+use slosh_test_lib::docs;
 use clap::{Arg, ArgMatches, Command};
 use mdbook::book::{Book, BookItem};
 use mdbook::errors::Error;
@@ -12,6 +13,8 @@ use semver::{Version, VersionReq};
 use std::io;
 use std::process;
 
+pub const SLOSH_AS_CODE_BLOCK_TAG: &str = "slosh";
+
 pub fn make_app() -> Command {
     Command::new("mdbook-slosh-eval")
         .about(
@@ -112,7 +115,7 @@ mod slosh_eval_lib {
                         match event {
                             Event::Start(Tag::CodeBlock(ref kind)) => match kind {
                                 CodeBlockKind::Fenced(name) if !tracking => {
-                                    if name.starts_with("slosh") && !name.contains("no-execute") {
+                                    if name.starts_with(SLOSH_AS_CODE_BLOCK_TAG) && !name.contains("no-execute") {
                                         slosh_code_block_num += 1;
                                         log::debug!(
                                             "File: {}: block #{}",
@@ -142,10 +145,10 @@ mod slosh_eval_lib {
                                     buf += "\n";
                                 }
                                 tracking = false;
-                                log::debug!("```slosh\n{}", buf);
+                                log::debug!("```{}\n{}", SLOSH_AS_CODE_BLOCK_TAG, buf);
                                 log::debug!("```");
                                 events.push(Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(
-                                    "slosh".into(),
+                                    SLOSH_AS_CODE_BLOCK_TAG.into(),
                                 ))));
                                 events.push(Event::Text(buf.clone().into()));
                                 events.push(Event::End(TagEnd::CodeBlock));
@@ -187,6 +190,7 @@ mod slosh_eval_lib {
 
     fn exec_code(code: String) -> String {
         let mut vm = slosh_lib::new_slosh_vm_with_builtins_and_core();
+        docs::add_builtins(&mut vm);
 
         let code = format!(
             r#"(import test)
diff --git a/doc/mk-site.sh b/doc/mk-site.sh
index a317962a27..6681a06e2f 100755
--- a/doc/mk-site.sh
+++ b/doc/mk-site.sh
@@ -45,4 +45,6 @@ export PATH="$PATH:./mdbook-slosh-eval/target/debug"
 #
 #../target/debug/slosh -c "(build-doc \"${PWD}\")"
 
+# doing this because im tryingto use the mk-site.slosh script but don't
+# see a need to re-write this shell script in slosh at this moment too.
 ./search-hack-patch.sh
diff --git a/doc/src/SUMMARY.md b/doc/src/SUMMARY.md
index 98ebdbdf86..92706f8a8e 100644
--- a/doc/src/SUMMARY.md
+++ b/doc/src/SUMMARY.md
@@ -8,6 +8,7 @@
 - [Syntax and Macros](./syntax-and-macros.md)
 - [Iterators](./iterators.md)
 - [Shell Redirects](./shell-redirects.md)
+- [Transition from Legacy](./transition-from-legacy.md)
 
 # General
 
diff --git a/doc/src/transition-from-legacy.md b/doc/src/transition-from-legacy.md
new file mode 100644
index 0000000000..856a8db7aa
--- /dev/null
+++ b/doc/src/transition-from-legacy.md
@@ -0,0 +1,10 @@
+# Transition Tracking
+
+## TODO sort these and then try to get out of the google doc (maybe need a hash map that pre-maps the one's we're skipping so the count is accurate)
+```slosh
+(get-globals-sorted)
+```
+
+```slosh
+(legacy_forms)
+```
diff --git a/slosh_test/Cargo.toml b/slosh_test/Cargo.toml
index 8ecfe960fe..c9cc6da864 100644
--- a/slosh_test/Cargo.toml
+++ b/slosh_test/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 
 [dependencies]
 slosh_lib = { path = "../slosh_lib" }
+slosh_test_lib = { path = "../slosh_test_lib" }
 regex = { workspace = true }
 lazy_static = { workspace = true }
 bridge_adapters = { path = "../bridge_adapters" }
diff --git a/slosh_test/src/main.rs b/slosh_test/src/main.rs
index a12553a1dd..7a9d244d34 100644
--- a/slosh_test/src/main.rs
+++ b/slosh_test/src/main.rs
@@ -1,12 +1,11 @@
-pub mod docs;
-
+use slosh_test_lib::docs;
 use bridge_adapters::add_builtin;
 use compile_state::state::SloshVm;
 use sl_compiler::load_eval::run_reader;
 use sl_compiler::Reader;
 use slosh_lib::run;
-use slvm::{VMError, VMResult, Value};
 use std::process;
+use slvm::{VMError, VMResult, Value};
 
 pub const VERSION_STRING: &str = env!("VERSION_STRING");
 
@@ -17,6 +16,7 @@ fn version(vm: &mut SloshVm, registers: &[Value]) -> VMResult<Value> {
     Ok(vm.alloc_string(VERSION_STRING.to_string()))
 }
 
+
 fn modify_vm(vm: &mut SloshVm) {
     docs::add_builtins(vm);
 
diff --git a/slosh_test_lib/README.md b/slosh_test_lib/README.md
new file mode 100644
index 0000000000..c2b790b368
--- /dev/null
+++ b/slosh_test_lib/README.md
@@ -0,0 +1,3 @@
+The slosh_test crate contains some special functions that use additional dependencies
+used to build slosh documentation and run the slosh tests. These actions can
+be performed manually but are also done by CI.
diff --git a/slosh_test_lib/build.rs b/slosh_test_lib/build.rs
new file mode 100644
index 0000000000..463a43aa20
--- /dev/null
+++ b/slosh_test_lib/build.rs
@@ -0,0 +1,105 @@
+use std::env::consts::{ARCH, OS};
+use std::process::Command;
+
+use chrono::prelude::Utc;
+
+#[cfg(debug_assertions)]
+const BUILD_TYPE: &str = "debug";
+#[cfg(not(debug_assertions))]
+const BUILD_TYPE: &str = "release";
+
+fn main() {
+    let version_string = if have_git() {
+        format!(
+            "{} {} ({}:{}{}, {} build, {} [{}], {} UTC [{}])",
+            env!("CARGO_PKG_NAME"),
+            env!("CARGO_PKG_VERSION"),
+            get_branch_name(),
+            get_commit_hash(),
+            if is_working_tree_clean() { "" } else { "+" },
+            BUILD_TYPE,
+            OS,
+            ARCH,
+            Utc::now().format("%b %d %Y, %T"),
+            get_rustc_version(),
+        )
+    } else {
+        format!(
+            "{} {} ({} build, {} [{}], {} UTC [{}])",
+            env!("CARGO_PKG_NAME"),
+            env!("CARGO_PKG_VERSION"),
+            BUILD_TYPE,
+            OS,
+            ARCH,
+            Utc::now().format("%b %d %Y, %T"),
+            get_rustc_version(),
+        )
+    };
+
+    println!("cargo:rustc-env=VERSION_STRING={}", version_string);
+}
+
+fn have_git() -> bool {
+    Command::new("git")
+        .arg("--version")
+        .current_dir(env!("CARGO_MANIFEST_DIR"))
+        .output()
+        .is_ok()
+}
+
+fn get_commit_hash() -> String {
+    let output = Command::new("git")
+        .arg("log")
+        .arg("-1")
+        .arg("--pretty=format:%h") // Abbreviated commit hash
+        // .arg("--pretty=format:%H") // Full commit hash
+        .current_dir(env!("CARGO_MANIFEST_DIR"))
+        .output()
+        .unwrap();
+
+    assert!(output.status.success());
+
+    String::from_utf8_lossy(&output.stdout).to_string()
+}
+
+fn get_branch_name() -> String {
+    let output = Command::new("git")
+        .arg("rev-parse")
+        .arg("--abbrev-ref")
+        .arg("HEAD")
+        .current_dir(env!("CARGO_MANIFEST_DIR"))
+        .output()
+        .unwrap();
+
+    assert!(output.status.success());
+
+    String::from_utf8_lossy(&output.stdout)
+        .trim_end()
+        .to_string()
+}
+
+fn is_working_tree_clean() -> bool {
+    let status = Command::new("git")
+        .arg("diff")
+        .arg("--quiet")
+        .arg("--exit-code")
+        .current_dir(env!("CARGO_MANIFEST_DIR"))
+        .status()
+        .unwrap();
+
+    status.code().unwrap() == 0
+}
+
+fn get_rustc_version() -> String {
+    let output = Command::new("rustc")
+        .arg("--version")
+        .current_dir(env!("CARGO_MANIFEST_DIR"))
+        .output()
+        .unwrap();
+
+    assert!(output.status.success());
+
+    String::from_utf8_lossy(&output.stdout)
+        .trim_end()
+        .to_string()
+}
diff --git a/slosh_test_lib/run-tests.slosh b/slosh_test_lib/run-tests.slosh
new file mode 100755
index 0000000000..e01be978e9
--- /dev/null
+++ b/slosh_test_lib/run-tests.slosh
@@ -0,0 +1,28 @@
+#!/usr/bin/env slosh_test
+
+(let (globals (get-globals-sorted)
+      globals-len (len globals)
+      i 0
+      failing-tests {})
+    (while (< i globals-len)
+        (prn "Symbol: " globals.~i)
+        (prn "===")
+        (let (doc (doc-map globals.~i))
+        ;; for some reason printing usage for vec-slice causes rust to panic with 'Handle 2045 is not a string!'
+            (prn "Usage: " (str doc.:usage))
+            (prn "Description: " (str doc.:description))
+            (prn "Section: " (str doc.:section))
+            (if (not (err? (get failing-tests (->key globals.~i))))
+                (prn "~~~~~~~~~~~~~~~~~~~~~ Skipping failing test")
+                (let (example (str doc.:example)
+                              read-in (read-all example))
+                    (prn "Example: " example)
+                    (dotimes-i j (len read-in)
+                        (let (line (prn (str read-in.~j))
+                            evaled (eval read-in.~j))
+                            (if (err? evaled)
+                                (do (prn "Err: " (str evaled))
+                                   (err (mk-err :test (str "Err: " evaled))))
+                                (prn "Result: " (str evaled)))))))
+        (prn "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
+        (inc! i))))
diff --git a/slosh_test/src/docs.rs b/slosh_test_lib/src/docs.rs
similarity index 100%
rename from slosh_test/src/docs.rs
rename to slosh_test_lib/src/docs.rs
diff --git a/slosh_test/src/docs/legacy.rs b/slosh_test_lib/src/docs/legacy.rs
similarity index 100%
rename from slosh_test/src/docs/legacy.rs
rename to slosh_test_lib/src/docs/legacy.rs
diff --git a/slosh_test_lib/src/lib.rs b/slosh_test_lib/src/lib.rs
new file mode 100644
index 0000000000..733a3e6ed6
--- /dev/null
+++ b/slosh_test_lib/src/lib.rs
@@ -0,0 +1 @@
+pub mod docs;
\ No newline at end of file
diff --git a/slosh_test_lib/tests/slosh-tests.rs b/slosh_test_lib/tests/slosh-tests.rs
new file mode 100644
index 0000000000..a5989cc784
--- /dev/null
+++ b/slosh_test_lib/tests/slosh-tests.rs
@@ -0,0 +1,50 @@
+use std::path::PathBuf;
+use std::process::Command;
+use tempfile::TempDir;
+
+pub fn get_slosh_exe() -> PathBuf {
+    PathBuf::from(env!("CARGO_BIN_EXE_slosh_test"))
+}
+
+// To run all tests in this executable
+//
+// cargo test --package slosh --test slosh-tests
+//
+// This integration test exists to test all the functions that slosh has by default
+// when loaded from the executable.
+
+#[test]
+/// look at all these amazing [environment variables](https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates)!
+/// EXE only works [with integration tests](https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html)
+/// To Execute:
+///     cargo test --package slosh_test --test slosh-tests run_slosh_tests -- --exact
+///
+fn run_slosh_tests() {
+    let test_script = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("run-tests.slosh");
+    eprintln!("Slosh doc test script: {test_script:?}");
+
+    let slosh_path = get_slosh_exe().into_os_string();
+    let slosh_path = slosh_path.to_str();
+
+    let tmp_dir = TempDir::with_prefix("test_load_path").unwrap();
+    let home_dir = tmp_dir.path().to_str();
+
+    let output = temp_env::with_var("HOME", home_dir, || {
+        println!("HOME:\n{}", env!("HOME"));
+        let output = Command::new(slosh_path.unwrap())
+            .arg(test_script)
+            .output()
+            .expect("Failed to execute command");
+        let s = String::from_utf8_lossy(output.stdout.as_slice());
+        println!("stdout:\n{}", s);
+        output
+    });
+
+    println!("status: {}", output.status);
+
+    assert!(
+        output.status.success(),
+        "Integration test script failed!: stderr:\n{}",
+        String::from_utf8_lossy(output.stderr.as_slice())
+    );
+}