mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 12:14:43 +00:00
perf: reduce IO
This commit is contained in:
parent
a7dbdb7c8d
commit
9e782bef2e
5 changed files with 51 additions and 21 deletions
|
@ -3,7 +3,7 @@ use std::path::{Path, PathBuf};
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
use crate::normalize_path;
|
use crate::normalize_path;
|
||||||
use crate::python_util::get_sys_path;
|
use crate::python_util::{_opt_which_python, get_sys_path};
|
||||||
use crate::style::colors::*;
|
use crate::style::colors::*;
|
||||||
use crate::style::RESET;
|
use crate::style::RESET;
|
||||||
|
|
||||||
|
@ -115,6 +115,7 @@ pub static ERG_PYSTD_PATH: OnceLock<PathBuf> = OnceLock::new();
|
||||||
pub static ERG_PKGS_PATH: OnceLock<PathBuf> = OnceLock::new();
|
pub static ERG_PKGS_PATH: OnceLock<PathBuf> = OnceLock::new();
|
||||||
pub static PYTHON_SYS_PATH: OnceLock<Vec<PathBuf>> = OnceLock::new();
|
pub static PYTHON_SYS_PATH: OnceLock<Vec<PathBuf>> = OnceLock::new();
|
||||||
pub static PYTHON_SITE_PACKAGES: OnceLock<Vec<PathBuf>> = OnceLock::new();
|
pub static PYTHON_SITE_PACKAGES: OnceLock<Vec<PathBuf>> = OnceLock::new();
|
||||||
|
pub static PYTHON_PATH: OnceLock<Result<String, String>> = OnceLock::new();
|
||||||
|
|
||||||
/// == `Path::new("~/.erg")` if ERG_PATH is not set
|
/// == `Path::new("~/.erg")` if ERG_PATH is not set
|
||||||
pub fn erg_path() -> &'static PathBuf {
|
pub fn erg_path() -> &'static PathBuf {
|
||||||
|
@ -154,6 +155,10 @@ pub fn python_site_packages() -> &'static Vec<PathBuf> {
|
||||||
PYTHON_SITE_PACKAGES.get_or_init(|| _python_site_packages().collect())
|
PYTHON_SITE_PACKAGES.get_or_init(|| _python_site_packages().collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn opt_which_python() -> Result<&'static String, &'static String> {
|
||||||
|
PYTHON_PATH.get_or_init(_opt_which_python).as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_std_decl_path(path: &Path) -> bool {
|
pub fn is_std_decl_path(path: &Path) -> bool {
|
||||||
path.starts_with(erg_pystd_path().as_path())
|
path.starts_with(erg_pystd_path().as_path())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! provides utilities for parser, compiler, and vm crate.
|
//! provides utilities for parser, compiler, and vm crate.
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::path::PathBuf;
|
use std::path::{Component, Path, PathBuf};
|
||||||
|
|
||||||
pub mod cache;
|
pub mod cache;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
@ -192,6 +192,33 @@ pub fn normalize_path(path: PathBuf) -> PathBuf {
|
||||||
PathBuf::from(lower)
|
PathBuf::from(lower)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cheap_canonicalize_path(path: &Path) -> PathBuf {
|
||||||
|
let mut components = path.components().peekable();
|
||||||
|
let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
|
||||||
|
components.next();
|
||||||
|
PathBuf::from(c.as_os_str())
|
||||||
|
} else {
|
||||||
|
PathBuf::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
for component in components {
|
||||||
|
match component {
|
||||||
|
Component::Prefix(..) => unreachable!(),
|
||||||
|
Component::RootDir => {
|
||||||
|
ret.push(component.as_os_str());
|
||||||
|
}
|
||||||
|
Component::CurDir => {}
|
||||||
|
Component::ParentDir => {
|
||||||
|
ret.pop();
|
||||||
|
}
|
||||||
|
Component::Normal(c) => {
|
||||||
|
ret.push(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use erg_common::trim_eliminate_top_indent;
|
/// use erg_common::trim_eliminate_top_indent;
|
||||||
/// let code = r#"
|
/// let code = r#"
|
||||||
|
|
|
@ -7,7 +7,8 @@ use std::path::{Component, Path, PathBuf};
|
||||||
use crate::consts::PYTHON_MODE;
|
use crate::consts::PYTHON_MODE;
|
||||||
use crate::env::erg_pkgs_path;
|
use crate::env::erg_pkgs_path;
|
||||||
use crate::traits::Immutable;
|
use crate::traits::Immutable;
|
||||||
use crate::{normalize_path, Str};
|
use crate::vfs::VFS;
|
||||||
|
use crate::{cheap_canonicalize_path, normalize_path, Str};
|
||||||
|
|
||||||
/// Guaranteed equivalence path.
|
/// Guaranteed equivalence path.
|
||||||
///
|
///
|
||||||
|
@ -59,7 +60,7 @@ impl Deref for NormalizedPathBuf {
|
||||||
|
|
||||||
impl NormalizedPathBuf {
|
impl NormalizedPathBuf {
|
||||||
pub fn new(path: PathBuf) -> Self {
|
pub fn new(path: PathBuf) -> Self {
|
||||||
NormalizedPathBuf(normalize_path(path.canonicalize().unwrap_or(path)))
|
NormalizedPathBuf(normalize_path(cheap_canonicalize_path(&path)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_path(&self) -> &Path {
|
pub fn as_path(&self) -> &Path {
|
||||||
|
@ -71,7 +72,7 @@ impl NormalizedPathBuf {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_read(&self) -> std::io::Result<String> {
|
pub fn try_read(&self) -> std::io::Result<String> {
|
||||||
std::fs::read_to_string(&self.0)
|
VFS.read(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ use std::io::Write;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{Command, ExitStatus, Stdio};
|
use std::process::{Command, ExitStatus, Stdio};
|
||||||
|
|
||||||
|
use crate::env::opt_which_python;
|
||||||
use crate::fn_name_full;
|
use crate::fn_name_full;
|
||||||
use crate::io::Output;
|
use crate::io::Output;
|
||||||
use crate::pathutil::remove_verbatim;
|
use crate::pathutil::remove_verbatim;
|
||||||
|
@ -608,7 +609,7 @@ fn get_poetry_virtualenv_path() -> Option<String> {
|
||||||
.then_some(path.trim().to_string())
|
.then_some(path.trim().to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn opt_which_python() -> Result<String, String> {
|
pub fn _opt_which_python() -> Result<String, String> {
|
||||||
if let Some(path) = which_python_from_toml() {
|
if let Some(path) = which_python_from_toml() {
|
||||||
return Ok(path);
|
return Ok(path);
|
||||||
}
|
}
|
||||||
|
@ -642,8 +643,8 @@ pub fn opt_which_python() -> Result<String, String> {
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn which_python() -> String {
|
fn which_python() -> &'static str {
|
||||||
opt_which_python().unwrap()
|
opt_which_python().as_ref().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn detect_magic_number(py_command: &str) -> u32 {
|
pub fn detect_magic_number(py_command: &str) -> u32 {
|
||||||
|
@ -672,7 +673,7 @@ pub fn detect_magic_number(py_command: &str) -> u32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn env_magic_number() -> u32 {
|
pub fn env_magic_number() -> u32 {
|
||||||
detect_magic_number(&which_python())
|
detect_magic_number(which_python())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn module_exists(py_command: &str, module: &str) -> bool {
|
pub fn module_exists(py_command: &str, module: &str) -> bool {
|
||||||
|
@ -786,7 +787,7 @@ pub fn get_python_version(py_command: &str) -> Option<PythonVersion> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn env_python_version() -> Option<PythonVersion> {
|
pub fn env_python_version() -> Option<PythonVersion> {
|
||||||
get_python_version(&which_python())
|
get_python_version(which_python())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_sys_path(working_dir: Option<&Path>) -> Result<Vec<PathBuf>, std::io::Error> {
|
pub fn get_sys_path(working_dir: Option<&Path>) -> Result<Vec<PathBuf>, std::io::Error> {
|
||||||
|
@ -834,9 +835,7 @@ fn exec_pyc_in(
|
||||||
"import marshal; exec(marshal.loads(open(r\"{}\", \"rb\").read()[16:]))",
|
"import marshal; exec(marshal.loads(open(r\"{}\", \"rb\").read()[16:]))",
|
||||||
file.as_ref().display()
|
file.as_ref().display()
|
||||||
);
|
);
|
||||||
let command = py_command
|
let command = py_command.map_or_else(|| which_python().to_string(), ToString::to_string);
|
||||||
.map(ToString::to_string)
|
|
||||||
.unwrap_or(which_python());
|
|
||||||
let mut out = if cfg!(windows) {
|
let mut out = if cfg!(windows) {
|
||||||
Command::new("cmd")
|
Command::new("cmd")
|
||||||
.arg("/C")
|
.arg("/C")
|
||||||
|
@ -876,9 +875,7 @@ pub fn exec_pyc(
|
||||||
if let Some(working_dir) = working_dir {
|
if let Some(working_dir) = working_dir {
|
||||||
return exec_pyc_in(file, py_command, working_dir, args, stdout);
|
return exec_pyc_in(file, py_command, working_dir, args, stdout);
|
||||||
}
|
}
|
||||||
let command = py_command
|
let command = py_command.map_or_else(|| which_python().to_string(), ToString::to_string);
|
||||||
.map(ToString::to_string)
|
|
||||||
.unwrap_or_else(which_python);
|
|
||||||
let mut out = if cfg!(windows) {
|
let mut out = if cfg!(windows) {
|
||||||
Command::new("cmd")
|
Command::new("cmd")
|
||||||
.arg("/C")
|
.arg("/C")
|
||||||
|
@ -902,9 +899,7 @@ pub fn exec_pyc(
|
||||||
|
|
||||||
/// evaluates over a shell, cause `python` may not exist as an executable file (like pyenv)
|
/// evaluates over a shell, cause `python` may not exist as an executable file (like pyenv)
|
||||||
pub fn _eval_pyc<S: Into<String>>(file: S, py_command: Option<&str>) -> String {
|
pub fn _eval_pyc<S: Into<String>>(file: S, py_command: Option<&str>) -> String {
|
||||||
let command = py_command
|
let command = py_command.map_or_else(|| which_python().to_string(), ToString::to_string);
|
||||||
.map(ToString::to_string)
|
|
||||||
.unwrap_or_else(which_python);
|
|
||||||
let out = if cfg!(windows) {
|
let out = if cfg!(windows) {
|
||||||
Command::new("cmd")
|
Command::new("cmd")
|
||||||
.arg("/C")
|
.arg("/C")
|
||||||
|
@ -966,7 +961,7 @@ pub fn env_spawn_py(code: &str) {
|
||||||
|
|
||||||
pub fn spawn_py(py_command: Option<&str>, code: &str) {
|
pub fn spawn_py(py_command: Option<&str>, code: &str) {
|
||||||
if cfg!(windows) {
|
if cfg!(windows) {
|
||||||
Command::new(py_command.unwrap_or(&which_python()))
|
Command::new(py_command.unwrap_or(which_python()))
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
.arg(code)
|
.arg(code)
|
||||||
.spawn()
|
.spawn()
|
||||||
|
@ -974,7 +969,7 @@ pub fn spawn_py(py_command: Option<&str>, code: &str) {
|
||||||
} else {
|
} else {
|
||||||
let exec_command = format!(
|
let exec_command = format!(
|
||||||
"{} -c \"{}\"",
|
"{} -c \"{}\"",
|
||||||
py_command.unwrap_or(&which_python()),
|
py_command.unwrap_or(which_python()),
|
||||||
escape_py_code(code)
|
escape_py_code(code)
|
||||||
);
|
);
|
||||||
Command::new("sh")
|
Command::new("sh")
|
||||||
|
|
|
@ -27,6 +27,7 @@ use erg_common::spawn::spawn_new_thread;
|
||||||
use erg_common::str::Str;
|
use erg_common::str::Str;
|
||||||
use erg_common::traits::{ExitStatus, New, Runnable, Stream};
|
use erg_common::traits::{ExitStatus, New, Runnable, Stream};
|
||||||
|
|
||||||
|
use erg_common::vfs::VFS;
|
||||||
use erg_parser::ast::{ClassAttr, Expr, InlineModule, Record, RecordAttrOrIdent, VarName, AST};
|
use erg_parser::ast::{ClassAttr, Expr, InlineModule, Record, RecordAttrOrIdent, VarName, AST};
|
||||||
use erg_parser::build_ast::{ASTBuildable, ASTBuilder as DefaultASTBuilder};
|
use erg_parser::build_ast::{ASTBuildable, ASTBuilder as DefaultASTBuilder};
|
||||||
use erg_parser::parse::SimpleParser;
|
use erg_parser::parse::SimpleParser;
|
||||||
|
@ -703,6 +704,7 @@ impl<ASTBuilder: ASTBuildable, HIRBuilder: Buildable>
|
||||||
.resolve_decl_path(path, cfg)
|
.resolve_decl_path(path, cfg)
|
||||||
.or_else(|| cfg.input.resolve_real_path(path, cfg))
|
.or_else(|| cfg.input.resolve_real_path(path, cfg))
|
||||||
};
|
};
|
||||||
|
VFS.cache_path(cfg.input.clone(), path.to_path_buf(), resolved.clone());
|
||||||
let import_path = match resolved {
|
let import_path = match resolved {
|
||||||
Some(path) => path,
|
Some(path) => path,
|
||||||
None if ERG_MODE => {
|
None if ERG_MODE => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue