diff --git a/crates/forge/build.rs b/crates/forge/build.rs index dcbb29981..10cefc78a 100644 --- a/crates/forge/build.rs +++ b/crates/forge/build.rs @@ -1,5 +1,4 @@ -use std::path::PathBuf; - +use steel::path::PathBuf; use steel::steel_vm::engine::Engine; fn main() { diff --git a/crates/steel-core/Cargo.toml b/crates/steel-core/Cargo.toml index 354e931c8..66ed91f64 100644 --- a/crates/steel-core/Cargo.toml +++ b/crates/steel-core/Cargo.toml @@ -43,7 +43,7 @@ steel-parser = { path = "../steel-parser", version = "0.7.0" } steel-derive = { path = "../steel-derive", version = "0.7.0" } cargo-steel-lib = { path = "../cargo-steel-lib", version = "0.2.0", optional = true } chrono = { version = "0.4.23", default-features = false, features = ["std", "clock"], optional = true } -env_home = "0.1.0" +env_home = { version = "0.1.0", optional = true } weak-table = "0.3.2" # TODO: Consider whether rand needs to be here rand = "0.9.0" @@ -98,10 +98,10 @@ ureq = { version = "3.0.12", optional = true } arc-swap = "1.7.1" md-5 = "0.10.6" -glob = "0.3.2" +glob = { version = "0.3.2", optional = true } # For helping discover the steel home location -xdg = "3.0.0" +xdg = { version = "3.0.0", optional = true } shared_vector = "0.4.4" @@ -118,7 +118,7 @@ js-sys = "0.3.69" polling = "3.10.0" [target.'cfg(not(any(target_family = "wasm", target_env = "newlib")))'.dependencies] -which = "8.0.0" +which = { version = "8.0.0", optional = true } [dev-dependencies] proptest = "1.1.0" @@ -127,7 +127,7 @@ criterion = "0.5.1" [features] # TODO: Deprecate the modules feature flag, it no longer does anything default = ["std", "modules"] -std = ["dep:chrono"] +std = ["dep:chrono", "dep:env_home", "dep:glob", "dep:xdg", "dep:which"] modules = [] jit = ["dep:cranelift", "dep:cranelift-module", "dep:cranelift-jit"] sandbox = [] diff --git a/crates/steel-core/src/compiler/compiler.rs b/crates/steel-core/src/compiler/compiler.rs index 2425d784d..221e277c2 100644 --- a/crates/steel-core/src/compiler/compiler.rs +++ b/crates/steel-core/src/compiler/compiler.rs @@ -26,12 +26,10 @@ use crate::{ parser::parser::Sources, }; +use crate::path::PathBuf; use alloc::borrow::Cow; use core::iter::Iterator; -use std::{ - collections::{HashMap, HashSet}, - path::PathBuf, -}; +use std::collections::{HashMap, HashSet}; use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet}; use serde::{Deserialize, Serialize}; @@ -742,7 +740,7 @@ impl Compiler { // Could fail here let parsed: core::result::Result, ParseError> = path .as_ref() - .map(|p| Parser::new_from_source(expr_str.as_ref(), p.clone(), Some(id))) + .map(|p| Parser::new_from_source(expr_str.as_ref(), p.to_path_buf(), Some(id))) .unwrap_or_else(|| Parser::new(expr_str.as_ref(), Some(id))) .without_lowering() .map(|x| x.and_then(lower_macro_and_require_definitions)) @@ -772,7 +770,7 @@ impl Compiler { // Could fail here let parsed: core::result::Result, ParseError> = path .as_ref() - .map(|p| Parser::new_from_source(expr_str.as_ref(), p.clone(), Some(id))) + .map(|p| Parser::new_from_source(expr_str.as_ref(), p.to_path_buf(), Some(id))) .unwrap_or_else(|| Parser::new(expr_str.as_ref(), Some(id))) .without_lowering() .map(|x| x.and_then(lower_macro_and_require_definitions)) diff --git a/crates/steel-core/src/compiler/modules.rs b/crates/steel-core/src/compiler/modules.rs index a24356e57..e8ecea91f 100644 --- a/crates/steel-core/src/compiler/modules.rs +++ b/crates/steel-core/src/compiler/modules.rs @@ -32,15 +32,14 @@ use rustc_hash::{FxHashMap, FxHashSet}; // use smallvec::SmallVec; use steel_parser::{ast::PROTO_HASH_GET, expr_list, parser::SourceId, span::Span}; -use thin_vec::{thin_vec, ThinVec}; - +use crate::path::PathBuf; use std::{ borrow::Cow, collections::{HashMap, HashSet}, io::Read, - path::PathBuf, sync::Arc, }; +use thin_vec::{thin_vec, ThinVec}; use crate::parser::expander::SteelMacro; use crate::stop; @@ -145,9 +144,11 @@ create_prelude!( #[cfg(not(target_family = "wasm"))] pub static STEEL_SEARCH_PATHS: Lazy>> = Lazy::new(|| { - std::env::var("STEEL_SEARCH_PATHS") - .ok() - .map(|x| std::env::split_paths(x.as_str()).collect::>()) + std::env::var("STEEL_SEARCH_PATHS").ok().map(|x| { + std::env::split_paths(x.as_str()) + .map(PathBuf::from) + .collect::>() + }) }); pub fn steel_search_dirs() -> Vec { @@ -161,11 +162,11 @@ pub fn steel_search_dirs() -> Vec { #[cfg(not(target_family = "wasm"))] pub static STEEL_HOME: Lazy> = Lazy::new(|| { std::env::var("STEEL_HOME").ok().or_else(|| { - let home = env_home::env_home_dir().map(|x| x.join(".steel")); + let home = env_home::env_home_dir().map(|x| PathBuf::from(x.join(".steel"))); if let Some(home) = home { if home.exists() { - return Some(home.into_os_string().into_string().unwrap()); + return Some(home.to_str().unwrap().to_owned()); } #[cfg(target_os = "windows")] @@ -174,14 +175,14 @@ pub static STEEL_HOME: Lazy> = Lazy::new(|| { eprintln!("Unable to create steel home directory {:?}: {}", home, e) } - return Some(home.into_os_string().into_string().unwrap()); + return Some(home.to_str().unwrap().to_owned()); } } #[cfg(not(target_os = "windows"))] { let bd = xdg::BaseDirectories::new(); - let home = bd.data_home; + let home = bd.data_home.map(PathBuf::from); home.map(|mut x: PathBuf| { x.push("steel"); @@ -196,7 +197,7 @@ pub static STEEL_HOME: Lazy> = Lazy::new(|| { } } - x.into_os_string().into_string().unwrap() + x.to_str().unwrap().to_owned() }) } @@ -1485,7 +1486,7 @@ impl CompiledModule { builtin_definitions.append(&mut provide_definitions); - let module = self.name.as_os_str().to_str().unwrap().to_owned(); + let module = self.name.as_path().as_os_str().to_str().unwrap().to_owned(); // Introduce a call to set the current module context? builtin_definitions.push(expr_list!( @@ -1657,7 +1658,9 @@ impl RequireObjectBuilder { } fn try_canonicalize(path: PathBuf) -> PathBuf { - std::fs::canonicalize(&path).unwrap_or_else(|_| path) + std::fs::canonicalize(&path) + .map(PathBuf::from) + .unwrap_or(path) } /* @@ -1796,7 +1799,7 @@ impl CompiledModuleCache { Ok(mut value) => { value.emitted = false; value.cached_prefix = - path_to_prefix_name(value.name.to_path_buf()).into(); + path_to_prefix_name(value.name.clone()).into(); log::info!( "Successfully read cached module in background -> {:?}", @@ -1848,7 +1851,7 @@ impl CompiledModuleCache { let mut value: CompiledModule = bincode::deserialize(&contents).unwrap(); value.emitted = false; - value.cached_prefix = path_to_prefix_name(value.name.to_path_buf()).into(); + value.cached_prefix = path_to_prefix_name(value.name.clone()).into(); for downstream in value .downstream @@ -1991,9 +1994,9 @@ impl<'a> ModuleBuilder<'a> { #[cfg(not(target_family = "wasm"))] let name = if let Some(p) = name { - std::fs::canonicalize(p)? + PathBuf::from(std::fs::canonicalize(p)?) } else { - std::env::current_dir()? + PathBuf::from(std::env::current_dir()?) }; #[cfg(target_family = "wasm")] @@ -3250,7 +3253,7 @@ impl<'a> ModuleBuilder<'a> { .sources .add_source(input.clone(), Some(self.name.clone())); - let parsed = Parser::new_from_source(&input, self.name.clone(), Some(id)) + let parsed = Parser::new_from_source(&input, self.name.to_path_buf(), Some(id)) .without_lowering() .map(|x| x.and_then(lower_macro_and_require_definitions)) .collect::, ParseError>>()?; @@ -3295,7 +3298,7 @@ impl<'a> ModuleBuilder<'a> { let exprs = guard.get(id).unwrap(); - let mut parsed = Parser::new_from_source(exprs, self.name.clone(), Some(id)) + let mut parsed = Parser::new_from_source(exprs, self.name.to_path_buf(), Some(id)) .without_lowering() .map(|x| x.and_then(lower_macro_and_require_definitions)) .collect::, ParseError>>()?; diff --git a/crates/steel-core/src/gc.rs b/crates/steel-core/src/gc.rs index 6109e0126..35394890d 100644 --- a/crates/steel-core/src/gc.rs +++ b/crates/steel-core/src/gc.rs @@ -5,10 +5,11 @@ use crate::rvals::SteelVal; #[cfg(not(feature = "sync"))] use core::cell::RefCell; +use crate::path::OsStr; use core::fmt::Pointer; use core::ops::Deref; +use std::fmt; use std::sync::atomic::{AtomicUsize, Ordering}; -use std::{ffi::OsStr, fmt}; pub static OBJECT_COUNT: AtomicUsize = AtomicUsize::new(0); pub(crate) static MAXIMUM_OBJECTS: usize = 50000; diff --git a/crates/steel-core/src/lib.rs b/crates/steel-core/src/lib.rs index 5a461df7e..9b8d92db0 100644 --- a/crates/steel-core/src/lib.rs +++ b/crates/steel-core/src/lib.rs @@ -7,6 +7,7 @@ mod env; #[macro_use] pub mod core; pub mod compiler; +pub mod path; pub mod primitives; pub mod time; #[macro_use] diff --git a/crates/steel-core/src/parser/expander.rs b/crates/steel-core/src/parser/expander.rs index d463b115b..6f88589a8 100644 --- a/crates/steel-core/src/parser/expander.rs +++ b/crates/steel-core/src/parser/expander.rs @@ -8,6 +8,7 @@ use crate::parser::tokens::TokenType; use crate::parser::span::Span; +use crate::path::PathBuf; use crate::rvals::{IntoSteelVal, Result}; use core::cell::RefCell; use quickscope::ScopeSet; @@ -16,7 +17,7 @@ use std::{ fs::File, io::{Read, Write}, iter::FromIterator, - path::{Path, PathBuf}, + path::Path, }; use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet}; @@ -39,7 +40,7 @@ fn update_extension(mut path: PathBuf, extension: &str) -> PathBuf { // Prepend the given path with the working directory pub fn path_from_working_dir>(path: P) -> std::io::Result { - let mut working_dir = std::env::current_dir()?; + let mut working_dir = PathBuf::from(std::env::current_dir()?); working_dir.push(path); Ok(working_dir) } diff --git a/crates/steel-core/src/parser/parser.rs b/crates/steel-core/src/parser/parser.rs index 55dfd1821..d5c0dd9ff 100644 --- a/crates/steel-core/src/parser/parser.rs +++ b/crates/steel-core/src/parser/parser.rs @@ -4,13 +4,14 @@ use crate::rvals::{IntoSteelVal, SteelComplex, SteelString}; use crate::HashSet; use crate::{parser::tokens::TokenType::*, rvals::FromSteelVal}; +use crate::path::PathBuf; use alloc::borrow::Cow; use alloc::sync::Arc; use num_rational::{BigRational, Rational32}; use once_cell::sync::Lazy; use parking_lot::Mutex; use rustc_hash::FxHashMap; -use std::path::{Path, PathBuf}; +use std::path::Path; use steel_parser::interner::InternedString; use steel_parser::tokens::{IntLiteral, NumberLiteral, RealLiteral, TokenType}; diff --git a/crates/steel-core/src/path.rs b/crates/steel-core/src/path.rs new file mode 100644 index 000000000..877a72d38 --- /dev/null +++ b/crates/steel-core/src/path.rs @@ -0,0 +1,251 @@ +#![allow(dead_code)] + +#[cfg(not(feature = "std"))] +use alloc::borrow::Cow; +#[cfg(not(feature = "std"))] +use alloc::borrow::ToOwned; +#[cfg(not(feature = "std"))] +use alloc::string::String; + +#[cfg(not(feature = "std"))] +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[cfg(feature = "std")] +pub use std::ffi::OsStr; + +#[cfg(not(feature = "std"))] +pub type OsStr = str; + +#[cfg(feature = "std")] +pub const MAIN_SEPARATOR_STR: &str = std::path::MAIN_SEPARATOR_STR; + +#[cfg(not(feature = "std"))] +pub const MAIN_SEPARATOR_STR: &str = "/"; + +#[cfg(feature = "std")] +pub type PathBuf = std::path::PathBuf; + +#[cfg(not(feature = "std"))] +#[derive(Clone, PartialEq, Eq, Hash, Default)] +pub struct PathBuf(String); + +#[cfg(not(feature = "std"))] +impl PathBuf { + #[inline] + pub fn new() -> Self { + Self(String::new()) + } + + #[inline] + pub fn as_str(&self) -> &str { + &self.0 + } + + #[inline] + pub fn as_os_str(&self) -> &OsStr { + self.0.as_str() + } + + #[inline] + pub fn as_path(&self) -> &str { + &self.0 + } + + #[inline] + pub fn push(&mut self, segment: &str) { + if !self.0.is_empty() && !self.0.ends_with('/') { + self.0.push('/'); + } + self.0.push_str(segment); + } + + #[inline] + pub fn join(&self, segment: &str) -> Self { + let mut next = self.clone(); + next.push(segment); + next + } + + #[inline] + pub fn exists(&self) -> bool { + false + } + + #[inline] + pub fn is_file(&self) -> bool { + false + } + + #[inline] + pub fn is_dir(&self) -> bool { + false + } + + #[inline] + pub fn pop(&mut self) -> bool { + if self.0.is_empty() { + return false; + } + + let trimmed_len = self.0.trim_end_matches('/').len(); + self.0.truncate(trimmed_len); + + if self.0.is_empty() { + return false; + } + + if let Some(idx) = self.0.rfind('/') { + self.0.truncate(idx); + } else { + self.0.clear(); + } + + true + } + + #[inline] + pub fn set_extension(&mut self, extension: &str) -> bool { + if self.0.is_empty() { + return false; + } + + let trimmed_len = self.0.trim_end_matches('/').len(); + self.0.truncate(trimmed_len); + + if self.0.is_empty() { + return false; + } + + let (prefix, file) = match self.0.rsplit_once('/') { + Some((prefix, file)) => (Some(prefix.to_owned()), file), + None => (None, self.0.as_str()), + }; + + if file.is_empty() { + return false; + } + + let stem = match file.rfind('.') { + Some(idx) => &file[..idx], + None => file, + }; + + let mut new_file = stem.to_owned(); + if !extension.is_empty() { + if !new_file.is_empty() { + new_file.push('.'); + } + new_file.push_str(extension); + } + + self.0.clear(); + if let Some(prefix) = prefix { + if !prefix.is_empty() { + self.0.push_str(&prefix); + if !self.0.ends_with('/') { + self.0.push('/'); + } + } + } + + self.0.push_str(&new_file); + true + } + + #[inline] + pub fn to_string_lossy(&self) -> Cow<'_, str> { + Cow::Borrowed(&self.0) + } + + #[inline] + pub fn to_str(&self) -> Option<&str> { + Some(&self.0) + } + + #[inline] + pub fn to_path_buf(&self) -> Self { + self.clone() + } +} + +#[cfg(not(feature = "std"))] +impl From for PathBuf { + fn from(value: String) -> Self { + Self(value) + } +} + +#[cfg(not(feature = "std"))] +impl From<&str> for PathBuf { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + +#[cfg(not(feature = "std"))] +impl From<&PathBuf> for PathBuf { + fn from(value: &PathBuf) -> Self { + value.clone() + } +} + +#[cfg(not(feature = "std"))] +impl core::fmt::Debug for PathBuf { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::Debug::fmt(&self.0, f) + } +} + +#[cfg(not(feature = "std"))] +impl core::fmt::Display for PathBuf { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.0) + } +} + +#[cfg(not(feature = "std"))] +impl Serialize for PathBuf { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.0) + } +} + +#[cfg(not(feature = "std"))] +impl<'de> Deserialize<'de> for PathBuf { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let value = String::deserialize(deserializer)?; + Ok(Self(value)) + } +} + +#[cfg(not(feature = "std"))] +impl From for String { + fn from(value: PathBuf) -> Self { + value.0 + } +} + +#[cfg(not(feature = "std"))] +impl From<&PathBuf> for String { + fn from(value: &PathBuf) -> Self { + value.0.clone() + } +} + +#[cfg(not(feature = "std"))] +#[cfg(not(feature = "std"))] +impl core::str::FromStr for PathBuf { + type Err = core::convert::Infallible; + + fn from_str(s: &str) -> Result { + Ok(Self::from(s)) + } +} + +pub type OwnedPath = PathBuf; diff --git a/crates/steel-core/src/primitives/fs.rs b/crates/steel-core/src/primitives/fs.rs index e6b6c3ce5..af4b67a48 100644 --- a/crates/steel-core/src/primitives/fs.rs +++ b/crates/steel-core/src/primitives/fs.rs @@ -1,3 +1,4 @@ +use crate::path::PathBuf; use crate::rvals::{ self, AsRefMutSteelVal, AsRefSteelVal, Custom, IntoSteelVal, RestArgsIter, Result, SteelString, SteelVal, @@ -5,7 +6,7 @@ use crate::rvals::{ use crate::steel_vm::builtin::BuiltInModule; use crate::{steelerr, throw}; use std::env::{current_dir, set_current_dir}; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::fs::{self, DirEntry, Metadata, ReadDir}; use std::io; @@ -13,7 +14,7 @@ use std::io; fn get_extension_from_filename(filename: &str) -> Option<&str> { Path::new(filename) .extension() - .and_then(std::ffi::OsStr::to_str) + .and_then(crate::path::OsStr::to_str) } /// Copy files from source to destination recursively. @@ -64,7 +65,7 @@ pub fn glob(pattern: SteelString, mut rest: RestArgsIter<'_, &SteelVal>) -> Resu pub fn glob_paths_next(paths: &SteelVal) -> Result { let mut paths = glob::Paths::as_mut_ref(paths)?; match paths.next() { - Some(Ok(v)) => v.into_steelval(), + Some(Ok(v)) => PathBuf::from(v).into_steelval(), Some(Err(e)) => crate::stop!(Generic => "glob-iter-next!: {:?}", e), None => Ok(SteelVal::BoolV(false)), } diff --git a/crates/steel-core/src/primitives/http.rs b/crates/steel-core/src/primitives/http.rs index bf7dc31c1..817f28aed 100644 --- a/crates/steel-core/src/primitives/http.rs +++ b/crates/steel-core/src/primitives/http.rs @@ -76,7 +76,8 @@ fn download_file(_url: &SteelString, _file: &SteelString) -> Result { #[cfg(feature = "ureq")] { - use std::{fs, path::PathBuf}; + use crate::path::PathBuf; + use std::fs; let url = _url.as_str(); let file = PathBuf::from(_file.as_str()); diff --git a/crates/steel-core/src/steel_vm/dylib.rs b/crates/steel-core/src/steel_vm/dylib.rs index f78eacfe7..aed070626 100644 --- a/crates/steel-core/src/steel_vm/dylib.rs +++ b/crates/steel-core/src/steel_vm/dylib.rs @@ -2,7 +2,7 @@ use std::{ cell::RefCell, collections::HashMap, - path::{Path, PathBuf}, + path::Path, rc::Rc, sync::{Arc, Mutex}, }; @@ -18,6 +18,7 @@ use once_cell::sync::Lazy; use crate::{ compiler::modules::steel_home, + path::PathBuf, rvals::{IntoSteelVal, SteelString, SteelVal}, }; diff --git a/crates/steel-core/src/steel_vm/engine.rs b/crates/steel-core/src/steel_vm/engine.rs index 4a986a96f..9d059024b 100644 --- a/crates/steel-core/src/steel_vm/engine.rs +++ b/crates/steel-core/src/steel_vm/engine.rs @@ -12,6 +12,7 @@ use super::{ffi::FFIModule, ffi::FFIWrappedModule}; #[cfg(feature = "dylibs")] use super::dylib::DylibContainers; +use crate::path::PathBuf; use crate::{ compiler::{ compiler::{Compiler, SerializableCompiler}, @@ -63,7 +64,7 @@ use std::{ borrow::Cow, cell::{Cell, RefCell}, collections::{HashMap, HashSet}, - path::{Path, PathBuf}, + path::Path, rc::Rc, sync::{ atomic::{AtomicBool, AtomicUsize, Ordering}, @@ -2742,7 +2743,7 @@ fn test_raw_engine() { fn test_ctx_func() { let mut engine = Engine::new(); - let mut module = BuiltInModule::new("test/module"); + let mut module = BuiltInModule::new("test/module-ctx-func"); module.register_fn("foo", |implicit: SteelVal| { println!("Called with implicit: {}", implicit); @@ -2754,7 +2755,9 @@ fn test_ctx_func() { engine.register_module(module); - engine.run("(require-builtin test/module)").unwrap(); + engine + .run("(require-builtin test/module-ctx-func)") + .unwrap(); engine.run("(foo)").unwrap(); engine.update_value("global-context", SteelVal::IntV(10)); engine.run("(foo)").unwrap(); @@ -2764,7 +2767,7 @@ fn test_ctx_func() { fn test_ctx_func_registration() { let mut engine = Engine::new(); - let mut module = BuiltInModule::new("test/module-func"); + let mut module = BuiltInModule::new("test/module-ctx-func-registration"); engine.register_value("global-context", SteelVal::StringV("Hello world!".into())); module.register_fn_with_ctx("global-context", "foo", |implicit: SteelVal| { @@ -2773,7 +2776,9 @@ fn test_ctx_func_registration() { engine.register_module(module); - engine.run("(require-builtin test/module-func)").unwrap(); + engine + .run("(require-builtin test/module-ctx-func-registration)") + .unwrap(); engine.run("(foo)").unwrap(); engine.update_value("global-context", SteelVal::IntV(10)); engine.run("(foo)").unwrap(); @@ -2783,7 +2788,7 @@ fn test_ctx_func_registration() { fn test_ctx_func_registration_multiple() { let mut engine = Engine::new(); - let mut module = BuiltInModule::new("test/module-ctx"); + let mut module = BuiltInModule::new("test/module-ctx-func-registration-multiple"); engine.register_value("global-context", SteelVal::StringV("Hello world!".into())); module.register_fn_with_ctx("global-context", "foo", |implicit: SteelVal| { @@ -2800,7 +2805,9 @@ fn test_ctx_func_registration_multiple() { engine.register_module(module); - engine.run("(require-builtin test/module-ctx)").unwrap(); + engine + .run("(require-builtin test/module-ctx-func-registration-multiple)") + .unwrap(); engine.run("(bar 10)").unwrap(); engine.update_value("global-context", SteelVal::IntV(10)); engine.run("(bar 100)").unwrap(); diff --git a/crates/steel-core/src/steel_vm/primitives.rs b/crates/steel-core/src/steel_vm/primitives.rs index cbc50fadb..eb19d4b0a 100644 --- a/crates/steel-core/src/steel_vm/primitives.rs +++ b/crates/steel-core/src/steel_vm/primitives.rs @@ -2272,7 +2272,7 @@ fn meta_module() -> BuiltInModule { .register_fn("current-os!", || std::env::consts::OS) .register_fn("target-arch!", || std::env::consts::ARCH) .register_fn("platform-dll-prefix!", || std::env::consts::DLL_PREFIX) - .register_fn("path-separator", || std::path::MAIN_SEPARATOR_STR) + .register_fn("path-separator", || crate::path::MAIN_SEPARATOR_STR) .register_fn("platform-dll-extension!", || { std::env::consts::DLL_EXTENSION }) diff --git a/crates/steel-core/src/steel_vm/vm.rs b/crates/steel-core/src/steel_vm/vm.rs index 865e89510..8c7af83e6 100644 --- a/crates/steel-core/src/steel_vm/vm.rs +++ b/crates/steel-core/src/steel_vm/vm.rs @@ -44,6 +44,7 @@ use crate::{ values::transducers::Transducers, }; +use crate::path::PathBuf; use crate::{ env::Env, gc::Gc, @@ -57,7 +58,6 @@ use core::hash::Hash; use core::{cell::RefCell, iter::Iterator}; use std::collections::HashMap; use std::io::Read as _; -use std::path::PathBuf; use std::sync::atomic::AtomicBool; use std::sync::Mutex; @@ -5811,7 +5811,7 @@ fn emit_expanded_file(path: String) { let contents = std::fs::read_to_string(&path).unwrap(); - engine.expand_to_file(contents, std::path::PathBuf::from(path)) + engine.expand_to_file(contents, PathBuf::from(path)) } #[steel_derive::function(name = "load-expanded", arity = "Exact(1)")] @@ -5928,7 +5928,7 @@ fn eval_file_impl(ctx: &mut crate::steel_vm::vm::VmCore, args: &[SteelVal]) -> R .thread .compiler .write() - .compile_executable(exprs, Some(std::path::PathBuf::from(path.as_str()))); + .compile_executable(exprs, Some(PathBuf::from(path.as_str()))); ctx.thread .compiler diff --git a/crates/steel-core/tests/testbench.rs b/crates/steel-core/tests/testbench.rs index a055aa7b7..d3847ba3d 100644 --- a/crates/steel-core/tests/testbench.rs +++ b/crates/steel-core/tests/testbench.rs @@ -48,7 +48,7 @@ fn module_test() { file.read_to_string(&mut exprs).unwrap(); evaluator - .compile_and_run_raw_program_with_path(exprs, path_buf) + .compile_and_run_raw_program_with_path(exprs, path_buf.into()) .unwrap(); test_line("(a 10)", &["127"], &mut evaluator); test_line("(b 20)", &["47"], &mut evaluator); @@ -67,7 +67,7 @@ fn macro_provide_module_test() { file.read_to_string(&mut exprs).unwrap(); evaluator - .compile_and_run_raw_program_with_path(exprs, path_buf) + .compile_and_run_raw_program_with_path(exprs, path_buf.into()) .unwrap(); test_line("bar", &["10"], &mut evaluator); test_line("baz", &["10"], &mut evaluator); @@ -86,7 +86,7 @@ fn macro_provide_module_test_loading() { file.read_to_string(&mut exprs).unwrap(); evaluator - .compile_and_run_raw_program_with_path(exprs, path_buf) + .compile_and_run_raw_program_with_path(exprs, path_buf.into()) .unwrap(); test_line("bar", &["10"], &mut evaluator); test_line("baz", &["10"], &mut evaluator); diff --git a/crates/steel-doc/src/lib.rs b/crates/steel-doc/src/lib.rs index 6a3f5b68a..34b729ba1 100644 --- a/crates/steel-doc/src/lib.rs +++ b/crates/steel-doc/src/lib.rs @@ -1,6 +1,8 @@ #![allow(unused)] -use std::{env::current_dir, error::Error, io::BufWriter, path::PathBuf}; +use std::{env::current_dir, error::Error, io::BufWriter}; + +use steel::path::PathBuf; use steel::compiler::modules::MANGLER_PREFIX; use steel::steel_vm::engine::Engine; @@ -19,7 +21,7 @@ impl DocumentGenerator { pub fn new(output_dir: Option) -> Self { let output_dir = output_dir.unwrap_or({ // TODO: Come back and remove this unwrap - let mut current_dir = current_dir().unwrap(); + let mut current_dir = PathBuf::from(current_dir().unwrap()); current_dir.push("/docs"); @@ -126,7 +128,7 @@ pub fn walk_dir( let directory_contents = path.read_dir()?.collect::, _>>()?; for file in directory_contents { - let path = file.path(); + let path = PathBuf::from(file.path()); walk_dir(writer, path, vm)?; } } else if path.extension().and_then(|x| x.to_str()) == Some("scm") diff --git a/crates/steel-language-server/src/backend.rs b/crates/steel-language-server/src/backend.rs index 7c8d81f4a..bd67fc923 100644 --- a/crates/steel-language-server/src/backend.rs +++ b/crates/steel-language-server/src/backend.rs @@ -4,7 +4,6 @@ use std::{ cell::RefCell, collections::{HashMap, HashSet}, error::Error, - path::PathBuf, sync::{Arc, Mutex, RwLock}, }; @@ -33,6 +32,7 @@ use steel::{ span::Span, tryfrom_visitor::SyntaxObjectFromExprKindRef, }, + path::PathBuf, rvals::{AsRefSteelVal, FromSteelVal, SteelString}, steel_vm::{builtin::BuiltInModule, engine::Engine, register_fn::RegisterFn}, }; @@ -916,8 +916,8 @@ impl LanguageServer for Backend { .clone() .to_file_path(); if let Ok(module_path) = module_path { - let mut external_module_refs = - self.find_references_external_module(identifier, module_path); + let mut external_module_refs = self + .find_references_external_module(identifier, PathBuf::from(module_path)); found_locations.append(&mut external_module_refs); } } @@ -1331,7 +1331,7 @@ impl Backend { let require_objects = module.get_requires(); for req in require_objects { - if req.path.get_path().as_path() == module_path { + if req.path.get_path().as_path() == module_path.as_path() { // Note: Once the logging is fixed we can remove the clone here should_index.push((module, req)); } @@ -1848,7 +1848,7 @@ impl Backend { let now = std::time::Instant::now(); let expressions = guard.emit_expanded_ast_without_optimizations( &expression, - params.uri.to_file_path().ok(), + params.uri.to_file_path().ok().map(PathBuf::from), ); eprintln!("on change time: {:?}", now.elapsed()); diff --git a/crates/steel-language-server/src/diagnostics.rs b/crates/steel-language-server/src/diagnostics.rs index 14a6f86a3..104034402 100644 --- a/crates/steel-language-server/src/diagnostics.rs +++ b/crates/steel-language-server/src/diagnostics.rs @@ -3,7 +3,6 @@ use std::{ collections::{BTreeSet, HashMap}, iter::FlatMap, - path::PathBuf, }; use dashmap::DashSet; @@ -26,6 +25,7 @@ use steel::{ parser::{SourceId, SyntaxObjectId}, span::Span, }, + path::PathBuf, steel_vm::{builtin::Arity, engine::Engine}, stop, SteelVal, }; diff --git a/crates/steel-language-server/src/main.rs b/crates/steel-language-server/src/main.rs index 38ca88e6b..16743ef14 100644 --- a/crates/steel-language-server/src/main.rs +++ b/crates/steel-language-server/src/main.rs @@ -1,6 +1,5 @@ use std::{ collections::{HashMap, HashSet}, - path::PathBuf, sync::Arc, }; @@ -9,6 +8,7 @@ use dashmap::{DashMap, DashSet}; use steel::{ compiler::modules::MANGLER_PREFIX, parser::{expander::SteelMacro, interner::InternedString}, + path::PathBuf, steel_vm::{engine::Engine, register_fn::RegisterFn}, }; use steel_language_server::backend::{ @@ -53,7 +53,7 @@ async fn main() { let home_directory = lsp_home(); ENGINE.write().unwrap().register_module_resolver( - ExternalModuleResolver::new(&mut resolver_engine, PathBuf::from(home_directory)).unwrap(), + ExternalModuleResolver::new(&mut resolver_engine, home_directory).unwrap(), ); { @@ -141,7 +141,7 @@ async fn main() { eprintln!("Finished indexing workspace"); - let root = std::env::current_dir().unwrap(); + let root = PathBuf::from(std::env::current_dir().unwrap()); let (service, socket) = LspService::build(|client| Backend { config: Config::new(), diff --git a/crates/steel-repl/src/repl.rs b/crates/steel-repl/src/repl.rs index d6d752c69..559854a0b 100644 --- a/crates/steel-repl/src/repl.rs +++ b/crates/steel-repl/src/repl.rs @@ -5,9 +5,9 @@ use rustyline::{ Cmd, ConditionalEventHandler, Event, EventContext, EventHandler, KeyEvent, RepeatCount, }; use steel::compiler::modules::steel_home; +use steel::path::PathBuf; use steel::rvals::{Custom, SteelString}; -use std::borrow::Cow; use std::error::Error; use std::fmt::{Debug, Display}; use std::sync::atomic::{AtomicBool, Ordering}; @@ -18,7 +18,7 @@ use rustyline::error::ReadlineError; use rustyline::{config::Configurer, Editor}; -use std::path::{Path, PathBuf}; +use std::path::Path; use steel::{rvals::SteelVal, steel_vm::register_fn::RegisterFn}; use steel::steel_vm::engine::Engine; @@ -62,12 +62,16 @@ fn get_default_startup() -> ColoredString { fn get_default_repl_history_path() -> PathBuf { if let Some(val) = steel_home() { - let mut parsed_path = PathBuf::from(&val); - parsed_path = parsed_path.canonicalize().unwrap_or(parsed_path); + let mut parsed_path = PathBuf::from(val); + let canonicalized = parsed_path + .as_path() + .canonicalize() + .unwrap_or_else(|_| parsed_path.to_path_buf()); + parsed_path = PathBuf::from(canonicalized); parsed_path.push("history"); parsed_path } else { - let mut default_path = env_home::env_home_dir().unwrap_or_default(); + let mut default_path = PathBuf::from(env_home::env_home_dir().unwrap_or_default()); default_path.push(".steel/history"); default_path.to_string_lossy().into_owned(); default_path @@ -261,11 +265,11 @@ impl + Debug> Repl { rl.set_check_cursor_position(true); // Load repl history - let history_path: Cow = self + let history_path = self .history_path .as_ref() - .map(|p| Cow::Borrowed(p.as_ref())) - .unwrap_or_else(|| Cow::Owned(get_default_repl_history_path())); + .map(|p| p.as_ref().to_path_buf()) + .unwrap_or_else(|| get_default_repl_history_path().to_path_buf()); if rl.load_history(&history_path).is_err() && File::create(&history_path).is_err() { eprintln!("Unable to create repl history file {:?}", history_path) @@ -365,7 +369,7 @@ impl + Debug> Repl { clear_interrupted(); - finish_load_or_interrupt(&mut self.vm, exprs, path.to_path_buf()); + finish_load_or_interrupt(&mut self.vm, exprs, PathBuf::from(path)); } _ => { // TODO also include this for loading files diff --git a/src/lib.rs b/src/lib.rs index e1a1ba12c..fa94d7ad3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,12 +4,12 @@ extern crate steel_repl; use clap::{Args, Command, CommandFactory, Parser, ValueEnum, ValueHint}; use clap_complete::{generate, Generator, Shell}; +use steel::path::PathBuf; use steel::steel_vm::engine::Engine; use steel_doc::walk_dir; use steel_repl::{register_readline_module, run_repl}; use std::env::current_dir; -use std::path::{Path, PathBuf}; use std::{error::Error, fs}; use std::{io, process}; @@ -109,9 +109,13 @@ const DOC_OUTPUT_DIR: &str = "docs"; impl DocArgs { fn process(self, vm: &mut Engine) -> Result<(), Box> { let docs_with_defaults = - self.with_defaults(current_dir()?, Path::new(DOC_OUTPUT_DIR).to_path_buf()); + self.with_defaults(PathBuf::from(current_dir()?), PathBuf::from(DOC_OUTPUT_DIR)); let mut writer = std::io::BufWriter::new(std::io::stdout()); - walk_dir(&mut writer, docs_with_defaults.input_path.unwrap(), vm)?; + walk_dir( + &mut writer, + PathBuf::from(docs_with_defaults.input_path.unwrap()), + vm, + )?; Ok(()) } @@ -293,7 +297,7 @@ pub fn run(clap_args: SteelCliArgs) -> Result<(), Box> { } } (true, false) => vm - .emit_fully_expanded_ast(&contents, Some(path.clone())) + .emit_fully_expanded_ast(&contents, Some(PathBuf::from(path.clone()))) .map(|ast| format!("{:#?}", ast)), (false, true) => Engine::emit_ast_to_string(&contents), (false, false) => Engine::emit_ast(&contents).map(|ast| format!("{:#?}", ast)), @@ -328,7 +332,10 @@ pub fn run(clap_args: SteelCliArgs) -> Result<(), Box> { let contents = fs::read_to_string(&path).expect("Something went wrong reading the file"); - let res = vm.compile_and_run_raw_program_with_path(contents.clone(), path.clone()); + let res = vm.compile_and_run_raw_program_with_path( + contents.clone(), + PathBuf::from(path.clone()), + ); if let Err(e) = res { vm.raise_error(e); @@ -350,7 +357,8 @@ pub fn run(clap_args: SteelCliArgs) -> Result<(), Box> { // Something went wrong - TODO: Raise the error correctly let non_interactive_program = - Engine::create_non_interactive_program_image(entrypoint, file).unwrap(); + Engine::create_non_interactive_program_image(entrypoint, PathBuf::from(file)) + .unwrap(); let mut temporary_output = PathBuf::from("steel_target/src"); @@ -518,7 +526,7 @@ fn r7rs_benchmark_test_suite_two() { for bench in benches { let args = SteelCliArgs { action: None, - default_file: Some(PathBuf::from(bench)), + default_file: Some(PathBuf::from(*bench)), arguments: vec![], }; @@ -540,7 +548,7 @@ fn r7rs_benchmark_test_suite() { for bench in benches { let args = SteelCliArgs { action: None, - default_file: Some(PathBuf::from(bench)), + default_file: Some(PathBuf::from(*bench)), arguments: vec![], }; @@ -566,7 +574,7 @@ fn r7rs_benchmark_test_suite_three() { for bench in benches { let args = SteelCliArgs { action: None, - default_file: Some(PathBuf::from(bench)), + default_file: Some(PathBuf::from(*bench)), arguments: vec![], };