initial commit

This commit is contained in:
Viv Lim 2022-12-10 19:17:51 -08:00
commit ebcf8bfdfb
13 changed files with 398 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
*.code-workspace

4
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
/* for extension `arrterian.nix-env-selector` */
"nixEnvSelector.nixFile": "${workspaceRoot}/flake.nix"
}

23
Cargo.lock generated Normal file
View File

@ -0,0 +1,23 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "guile-goblins-rs"
version = "0.1.0"
dependencies = [
"rust-guile",
]
[[package]]
name = "pkg-config"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "rust-guile"
version = "0.1.6"
dependencies = [
"pkg-config",
]

10
Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "guile-goblins-rs"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
#rust-guile = "0.1.6"
rust-guile = { path = "../rust-guile" }

11
README.md Normal file
View File

@ -0,0 +1,11 @@
# guile-goblins-rs
attempt to run goblins-guile embedded in rust via rust-guile
## setup
if using nix, `nix develop`
if not, install guile 3 (! make sure it's 3)
`cargo run --example repl` (aliased to `repl` in `nix develop`) will launch the guile repl running inside of rust

63
default.nix Normal file
View File

@ -0,0 +1,63 @@
# default.nix
{ lib
, naersk
, stdenv
, clangStdenv
, hostPlatform
, targetPlatform
, pkg-config
, libiconv
, rustfmt
, cargo
, rustc
# , llvmPackages # Optional
# , protobuf # Optional
}:
let
cargoToml = (builtins.fromTOML (builtins.readFile ./Cargo.toml));
in
naersk.lib."${targetPlatform.system}".buildPackage rec {
src = ./.;
buildInputs = [
rustfmt
pkg-config
cargo
rustc
libiconv
];
checkInputs = [ cargo rustc ];
doCheck = true;
CARGO_BUILD_INCREMENTAL = "false";
RUST_BACKTRACE = "full";
copyLibs = true;
# Optional things you might need:
#
# If you depend on `libclang`:
# LIBCLANG_PATH = "${llvmPackages.libclang}/lib";
#
# If you depend on protobuf:
# PROTOC = "${protobuf}/bin/protoc";
# PROTOC_INCLUDE = "${protobuf}/include";
name = cargoToml.package.name;
version = cargoToml.package.version;
meta = with lib; {
description = cargoToml.package.description;
homepage = cargoToml.package.homepage;
license = with licenses; [ mit ];
maintainers = with maintainers; [ ];
};
postInstall = ''
#mkdir -p "$out/var/lib/bespoke/templates"
#cp ./templates/* "$out/var/lib/bespoke/templates"
'';
}

15
examples/hello.rs Normal file
View File

@ -0,0 +1,15 @@
use std::{sync::{atomic::{AtomicU8, Ordering}, Arc}, fs::canonicalize};
use guile_goblins_rs::start_scm;
use rust_guile::api::SchemeApi;
use std::fs;
fn main() {
let counter = Arc::new(AtomicU8::new(1));
let to_run = |api: SchemeApi| {
counter.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
println!("I'm running inside the fn {}", counter.load(Ordering::Relaxed));
api.load_file("/Users/vivlim/git/guile-goblins-rs/hello.scm");
};
start_scm(vec!["-s", "./hello.scm"], to_run);
// code after here is never reached because guile exits
println!("after run counter is {}", counter.load(std::sync::atomic::Ordering::Relaxed));
}

12
examples/repl.rs Normal file
View File

@ -0,0 +1,12 @@
use std::{sync::{atomic::{AtomicU8, Ordering}, Arc}};
use guile_goblins_rs::start_scm;
use rust_guile::api::SchemeApi;
fn main() {
// We want to run the contents of repl-init.scm before starting the repl, mostly to activate readline.
let to_run = |api: SchemeApi| {
api.load_file("./repl-init.scm");
};
start_scm(vec![], to_run); // start guile with no args = repl
// note execution stops here, because guile exits the process.
}

127
flake.lock Normal file
View File

@ -0,0 +1,127 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"naersk": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1662220400,
"narHash": "sha256-9o2OGQqu4xyLZP9K6kNe1pTHnyPz0Wr3raGYnr9AIgY=",
"owner": "nmattia",
"repo": "naersk",
"rev": "6944160c19cb591eb85bbf9b2f2768a935623ed3",
"type": "github"
},
"original": {
"owner": "nmattia",
"repo": "naersk",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1670587192,
"narHash": "sha256-h3DHD2WBddfZxRuceYBa54JZKF1z8O8dtYNZK5UvP/4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "aaac4123e3e33e779af54361a244857d029a64dd",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1670597555,
"narHash": "sha256-/k939P2S2246G6K5fyvC0U2IWvULhb4ZJg9K7ZxsX+k=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2dea0f4c2d6e4603f54b2c56c22367e77869490c",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1665296151,
"narHash": "sha256-uOB0oxqxN9K7XGF1hcnY+PQnlQJ+3bP2vCn/+Ru/bbc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "14ccaaedd95a488dd7ae142757884d8e125b3363",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"naersk": "naersk",
"nixpkgs": "nixpkgs_2",
"rust-overlay": "rust-overlay"
}
},
"rust-overlay": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1670639101,
"narHash": "sha256-UvPSgbtaOk9WcgVqywnvQXOEEHx6OXdG+QXIwnbyvCw=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "d00c488cb455c21fea731167bf8c1b8da605aac3",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

66
flake.nix Normal file
View File

@ -0,0 +1,66 @@
{
description = "uhhhhh goblins?";
# references
# https://github.com/oxalica/rust-overlay
# https://hoverbear.org/blog/a-flake-for-your-crate/
# https://srid.ca/rust-nix
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
naersk.url = "github:nmattia/naersk";
rust-overlay.url = "github:oxalica/rust-overlay";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, naersk, rust-overlay, flake-utils, ... }:
let
cargoToml = (builtins.fromTOML (builtins.readFile ./Cargo.toml));
in (flake-utils.lib.eachDefaultSystem (system:
let
# overlay containing a package built from this repo's Cargo.toml
mypkgoverlay = final: prev: {
"${cargoToml.package.name}" = final.callPackage ./. { inherit naersk; };
};
overlays = [ (import rust-overlay) mypkgoverlay ];
pkgs = import nixpkgs {
inherit system overlays;
};
in
with pkgs;
{
devShells.default = mkShell {
buildInputs = [
openssl
pkg-config
guile_3_0
(rust-bin.stable.latest.default.override {
extensions = ["rust-src"];
targets = [ ];
})
];
shellHook = ''
alias repl="cargo run --example repl"
echo "run 'repl' to start a repl embedded in rust"
'';
};
packages = {
"${cargoToml.package.name}" = pkgs."${cargoToml.package.name}";
};
defaultPackage = (import nixpkgs {
inherit system overlays;
})."${cargoToml.package.name}";
}
))
//
(
#flake-utils.lib.eachSystem [ "x86_64-linux" ] (system: {
({
nixosModule = (import ./modules self);
})
);
}

4
hello.scm Normal file
View File

@ -0,0 +1,4 @@
(display "hello from guile\n")
(hello-from-rust)
(use-modules (ice-9 readline))
(activate-readline)

2
repl-init.scm Normal file
View File

@ -0,0 +1,2 @@
(use-modules (ice-9 readline))
(activate-readline)

59
src/lib.rs Normal file
View File

@ -0,0 +1,59 @@
use rust_guile::{*, bindings::*, api::SchemeApi};
use std::ffi::CString;
extern "C" fn hello_from_rust() -> SCM {
// an example function demonstrating that Rust functions work in Scheme
println!("Hello from Rust!");
unsafe {
scm_from_int8(0)
}
}
pub fn start_scm<F>(args: Vec<&str>, with_api: F)
where F: FnMut(SchemeApi) {
init_scm();
register_void_function!(b"hello-from-rust\0", hello_from_rust);
init_and_use_api_scm(with_api);
let args: Vec<String> = args.into_iter().map(|arg| arg.to_string()).collect();
let mut args: Vec<Vec<i8>> = args.into_iter().map(|arg| {
let cstr = CString::new(arg.into_bytes()).expect("args should be valid to represent as cstring");
cstr.into_bytes_with_nul().into_iter().map(|b| b as i8).collect()
}).collect();
let argc: i32 = args.len() as i32;
let mut arg_ptrs: Vec<*mut i8> = args.iter_mut().map(|arg| arg.as_mut_ptr()).collect();
let argv = arg_ptrs.as_mut_ptr();
/* this was actually unnecessary because guile does inherit env variables. i was just doing (getenv TERM) instead of (getenv "TERM")
// set all the env variables that apply to the rust process
// collect the names of any that failed
let env_failed_to_set: Vec<String> = std::env::vars()
.map(|env| (env.clone(), setenv_scm(&env.0, &env.1)))
.filter_map(|res| match res {
(env, Err(_)) => Some(env.0),
_ => None
})
.collect();
if !env_failed_to_set.is_empty() {
println!("WARNING: env variables that couldn't be set: {}", env_failed_to_set.join(", "));
} */
// set something so i don't feel like i wasted time :)
setenv_scm("UPDOG", "yes").unwrap();
run_scm(argc, argv);
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
}
}