mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-02 21:44:34 +00:00
feat: let Shared: Send + Sync
This commit is contained in:
parent
4d9800716b
commit
0e42ab03ca
18 changed files with 197 additions and 174 deletions
9
Cargo.lock
generated
9
Cargo.lock
generated
|
@ -117,10 +117,13 @@ dependencies = [
|
|||
name = "erg_common"
|
||||
version = "0.6.13"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"backtrace-on-stack-overflow",
|
||||
"crossterm",
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
|
@ -276,6 +279,12 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
|
|
|
@ -4,11 +4,11 @@ use serde_json::Value;
|
|||
|
||||
use erg_common::config::{ErgConfig, Input};
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::env::erg_pystd_path;
|
||||
use erg_common::env::ERG_PYSTD_PATH;
|
||||
use erg_common::impl_u8_enum;
|
||||
use erg_common::python_util::BUILTIN_PYTHON_MODS;
|
||||
use erg_common::set::Set;
|
||||
use erg_common::shared::AtomicShared;
|
||||
use erg_common::shared::Shared;
|
||||
use erg_common::traits::Locational;
|
||||
|
||||
use erg_compiler::artifact::{BuildRunnable, Buildable};
|
||||
|
@ -174,7 +174,7 @@ impl<'b> CompletionOrderSetter<'b> {
|
|||
}
|
||||
}
|
||||
|
||||
type Cache = AtomicShared<Dict<String, Vec<CompletionItem>>>;
|
||||
type Cache = Shared<Dict<String, Vec<CompletionItem>>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CompletionCache {
|
||||
|
@ -296,7 +296,7 @@ fn load_modules(cfg: ErgConfig, cache: Cache) {
|
|||
if cache.get("<module>").is_none() {
|
||||
cache.insert("<module>".into(), module_completions());
|
||||
}
|
||||
let std_path = erg_pystd_path().display().to_string().replace('\\', "/");
|
||||
let std_path = ERG_PYSTD_PATH.display().to_string().replace('\\', "/");
|
||||
for (path, entry) in shared.py_mod_cache.iter() {
|
||||
let dir = entry.module.context.local_dir();
|
||||
let mod_name = path.display().to_string().replace('\\', "/");
|
||||
|
@ -316,7 +316,7 @@ fn load_modules(cfg: ErgConfig, cache: Cache) {
|
|||
|
||||
impl CompletionCache {
|
||||
pub fn new(cfg: ErgConfig) -> Self {
|
||||
let cache = AtomicShared::new(Dict::default());
|
||||
let cache = Shared::new(Dict::default());
|
||||
let clone = cache.clone();
|
||||
std::thread::spawn(move || {
|
||||
crate::_log!("load_modules");
|
||||
|
|
|
@ -12,7 +12,7 @@ use lsp_types::{
|
|||
};
|
||||
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::shared::AtomicShared;
|
||||
use erg_common::shared::Shared;
|
||||
use erg_common::traits::DequeStream;
|
||||
use erg_compiler::erg_parser::lex::Lexer;
|
||||
use erg_compiler::erg_parser::token::{Token, TokenStream};
|
||||
|
@ -50,13 +50,13 @@ impl FileCacheEntry {
|
|||
/// This struct can save changes in real-time & incrementally.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FileCache {
|
||||
pub files: AtomicShared<Dict<NormalizedUrl, FileCacheEntry>>,
|
||||
pub files: Shared<Dict<NormalizedUrl, FileCacheEntry>>,
|
||||
}
|
||||
|
||||
impl FileCache {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
files: AtomicShared::new(Dict::new()),
|
||||
files: Shared::new(Dict::new()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ use serde_json::Value;
|
|||
|
||||
use erg_common::config::ErgConfig;
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::env::erg_path;
|
||||
use erg_common::env::ERG_PATH;
|
||||
use erg_common::normalize_path;
|
||||
|
||||
use erg_compiler::artifact::{BuildRunnable, IncompleteArtifact};
|
||||
|
@ -224,7 +224,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
comp_cache: CompletionCache::new(cfg.copy()),
|
||||
cfg,
|
||||
home: normalize_path(std::env::current_dir().unwrap_or_default()),
|
||||
erg_path: erg_path(), // already normalized
|
||||
erg_path: ERG_PATH.clone(), // already normalized
|
||||
client_capas: ClientCapabilities::default(),
|
||||
disabled_features: vec![],
|
||||
opt_features: vec![],
|
||||
|
|
|
@ -33,7 +33,10 @@ version = "0.3"
|
|||
features = ["consoleapi"]
|
||||
|
||||
[dependencies]
|
||||
backtrace = "0.3"
|
||||
once_cell = "1.17"
|
||||
crossterm = { optional = true, version = "0.25.0" }
|
||||
parking_lot = "0.12"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
use std::borrow::{Borrow, ToOwned};
|
||||
use std::cell::RefCell;
|
||||
use std::hash::Hash;
|
||||
use std::sync::Arc;
|
||||
use std::thread::LocalKey;
|
||||
|
||||
use crate::dict::Dict;
|
||||
use crate::set::Set;
|
||||
use crate::shared::Shared;
|
||||
use crate::{ArcArray, Str};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CacheSet<T: ?Sized>(RefCell<Set<Arc<T>>>);
|
||||
pub struct CacheSet<T: ?Sized>(Shared<Set<Arc<T>>>);
|
||||
|
||||
impl<T: ?Sized> Default for CacheSet<T> {
|
||||
fn default() -> Self {
|
||||
|
@ -19,7 +19,7 @@ impl<T: ?Sized> Default for CacheSet<T> {
|
|||
|
||||
impl<T: ?Sized> CacheSet<T> {
|
||||
pub fn new() -> Self {
|
||||
Self(RefCell::new(Set::new()))
|
||||
Self(Shared::new(Set::new()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,6 @@ impl<T: Hash + Eq> CacheSet<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct CacheDict<K, V: ?Sized>(RefCell<Dict<K, Arc<V>>>);
|
||||
pub struct CacheDict<K, V: ?Sized>(Shared<Dict<K, Arc<V>>>);
|
||||
|
||||
pub struct GlobalCacheDict<K: 'static, V: ?Sized + 'static>(LocalKey<RefCell<CacheDict<K, V>>>);
|
||||
pub struct GlobalCacheDict<K: 'static, V: ?Sized + 'static>(LocalKey<Shared<CacheDict<K, V>>>);
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::process;
|
|||
use std::str::FromStr;
|
||||
|
||||
use crate::consts::ERG_MODE;
|
||||
use crate::env::{erg_py_external_lib_path, erg_pystd_path, erg_std_path, python_site_packages};
|
||||
use crate::env::{ERG_EXTERNAL_LIB_PATH, ERG_PYSTD_PATH, ERG_STD_PATH, PYTHON_SITE_PACKAGES};
|
||||
use crate::help_messages::{command_message, mode_message, OPTIONS};
|
||||
use crate::levenshtein::get_similar_name;
|
||||
use crate::pathutil::add_postfix_foreach;
|
||||
|
@ -581,12 +581,12 @@ impl Input {
|
|||
pub fn resolve_real_path(&self, path: &Path) -> Option<PathBuf> {
|
||||
if let Ok(path) = self.resolve_local(path) {
|
||||
Some(path)
|
||||
} else if let Ok(path) = erg_std_path()
|
||||
} else if let Ok(path) = ERG_STD_PATH
|
||||
.join(format!("{}.er", path.display()))
|
||||
.canonicalize()
|
||||
{
|
||||
Some(normalize_path(path))
|
||||
} else if let Ok(path) = erg_std_path()
|
||||
} else if let Ok(path) = ERG_STD_PATH
|
||||
.join(format!("{}", path.display()))
|
||||
.join("__init__.er")
|
||||
.canonicalize()
|
||||
|
@ -612,13 +612,12 @@ impl Input {
|
|||
if let Ok(path) = self.resolve_local_decl(path) {
|
||||
Some(path)
|
||||
} else {
|
||||
let py_roots = [erg_pystd_path, erg_py_external_lib_path];
|
||||
for root in py_roots {
|
||||
if let Some(path) = Self::resolve_std_decl_path(root(), path) {
|
||||
for root in [ERG_PYSTD_PATH.clone(), ERG_EXTERNAL_LIB_PATH.clone()] {
|
||||
if let Some(path) = Self::resolve_std_decl_path(root, path) {
|
||||
return Some(path);
|
||||
}
|
||||
}
|
||||
for site_packages in python_site_packages() {
|
||||
for site_packages in PYTHON_SITE_PACKAGES.clone() {
|
||||
if let Some(path) = Self::resolve_site_pkgs_decl_path(site_packages, path) {
|
||||
return Some(path);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use std::env::var;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use crate::normalize_path;
|
||||
use crate::python_util::get_sys_path;
|
||||
use crate::style::colors::*;
|
||||
|
@ -66,43 +68,19 @@ fn _python_site_packages() -> impl Iterator<Item = PathBuf> {
|
|||
})
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
pub static ERG_PATH: PathBuf = normalize_path(_erg_path());
|
||||
pub static ERG_STD_PATH: PathBuf = normalize_path(_erg_std_path());
|
||||
pub static ERG_STD_DECL_PATH: PathBuf = normalize_path(_erg_std_decl_path());
|
||||
pub static ERG_PYSTD_PATH: PathBuf = normalize_path(_erg_pystd_path());
|
||||
pub static ERG_EXTERNAL_LIB_PATH: PathBuf = normalize_path(_erg_external_lib_path());
|
||||
pub static PYTHON_SITE_PACKAGES: Vec<PathBuf> = _python_site_packages().collect();
|
||||
}
|
||||
|
||||
pub fn erg_path() -> PathBuf {
|
||||
ERG_PATH.with(|s| s.clone())
|
||||
}
|
||||
|
||||
pub fn erg_std_path() -> PathBuf {
|
||||
ERG_STD_PATH.with(|s| s.clone())
|
||||
}
|
||||
|
||||
pub fn erg_std_decl_path() -> PathBuf {
|
||||
ERG_STD_DECL_PATH.with(|s| s.clone())
|
||||
}
|
||||
|
||||
pub fn erg_pystd_path() -> PathBuf {
|
||||
ERG_PYSTD_PATH.with(|s| s.clone())
|
||||
}
|
||||
|
||||
pub fn erg_py_external_lib_path() -> PathBuf {
|
||||
ERG_EXTERNAL_LIB_PATH.with(|s| s.clone())
|
||||
}
|
||||
|
||||
pub fn python_site_packages() -> Vec<PathBuf> {
|
||||
PYTHON_SITE_PACKAGES.with(|s| s.clone())
|
||||
}
|
||||
pub static ERG_PATH: Lazy<PathBuf> = Lazy::new(|| normalize_path(_erg_path()));
|
||||
pub static ERG_STD_PATH: Lazy<PathBuf> = Lazy::new(|| normalize_path(_erg_std_path()));
|
||||
pub static ERG_STD_DECL_PATH: Lazy<PathBuf> = Lazy::new(|| normalize_path(_erg_std_decl_path()));
|
||||
pub static ERG_PYSTD_PATH: Lazy<PathBuf> = Lazy::new(|| normalize_path(_erg_pystd_path()));
|
||||
pub static ERG_EXTERNAL_LIB_PATH: Lazy<PathBuf> =
|
||||
Lazy::new(|| normalize_path(_erg_external_lib_path()));
|
||||
pub static PYTHON_SITE_PACKAGES: Lazy<Vec<PathBuf>> =
|
||||
Lazy::new(|| _python_site_packages().collect());
|
||||
|
||||
pub fn is_std_decl_path(path: &Path) -> bool {
|
||||
path.starts_with(erg_pystd_path())
|
||||
|| path.starts_with(erg_std_decl_path())
|
||||
|| path.starts_with(erg_py_external_lib_path())
|
||||
path.starts_with(ERG_PYSTD_PATH.as_path())
|
||||
|| path.starts_with(ERG_STD_DECL_PATH.as_path())
|
||||
|| path.starts_with(ERG_EXTERNAL_LIB_PATH.as_path())
|
||||
}
|
||||
|
||||
pub fn is_pystd_main_module(path: &Path) -> bool {
|
||||
|
@ -113,6 +91,6 @@ pub fn is_pystd_main_module(path: &Path) -> bool {
|
|||
} else {
|
||||
path.pop();
|
||||
}
|
||||
let pystd_path = erg_pystd_path();
|
||||
path == pystd_path
|
||||
// let pystd_path = erg_pystd_path();
|
||||
path == ERG_PYSTD_PATH.as_path()
|
||||
}
|
||||
|
|
|
@ -1,21 +1,17 @@
|
|||
use crate::shared::Shared;
|
||||
|
||||
thread_local! {
|
||||
static VAR_ID: Shared<usize> = Shared::new(0);
|
||||
}
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
pub static VAR_ID: Lazy<Shared<usize>> = Lazy::new(|| Shared::new(0));
|
||||
|
||||
pub fn fresh_varname() -> String {
|
||||
VAR_ID.with(|id| {
|
||||
*id.borrow_mut() += 1;
|
||||
let i = *id.borrow();
|
||||
*VAR_ID.borrow_mut() += 1;
|
||||
let i = *VAR_ID.borrow();
|
||||
format!("%v{i}")
|
||||
})
|
||||
}
|
||||
|
||||
pub fn fresh_param_name() -> String {
|
||||
VAR_ID.with(|id| {
|
||||
*id.borrow_mut() += 1;
|
||||
let i = *id.borrow();
|
||||
*VAR_ID.borrow_mut() += 1;
|
||||
let i = *VAR_ID.borrow();
|
||||
format!("%p{i}")
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
use std::cell::{Ref, RefCell, RefMut};
|
||||
// use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
// use std::rc::Rc;
|
||||
pub use parking_lot::{
|
||||
MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug)]
|
||||
/*#[derive(Debug)]
|
||||
pub struct Shared<T: ?Sized>(Rc<RefCell<T>>);
|
||||
|
||||
impl<T: PartialEq> PartialEq for Shared<T> {
|
||||
|
@ -108,14 +111,14 @@ impl<T: Clone> Shared<T> {
|
|||
pub fn clone_inner(&self) -> T {
|
||||
self.borrow().clone()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AtomicShared<T: ?Sized>(Arc<Mutex<T>>);
|
||||
pub struct Shared<T: ?Sized>(Arc<RwLock<T>>);
|
||||
|
||||
impl<T: PartialEq> PartialEq for AtomicShared<T>
|
||||
impl<T: PartialEq> PartialEq for Shared<T>
|
||||
where
|
||||
Mutex<T>: PartialEq,
|
||||
RwLock<T>: PartialEq,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
|
@ -123,35 +126,35 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Clone for AtomicShared<T> {
|
||||
fn clone(&self) -> AtomicShared<T> {
|
||||
impl<T: ?Sized> Clone for Shared<T> {
|
||||
fn clone(&self) -> Shared<T> {
|
||||
Self(Arc::clone(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq> Eq for AtomicShared<T> where Mutex<T>: Eq {}
|
||||
impl<T: Eq> Eq for Shared<T> where RwLock<T>: Eq {}
|
||||
|
||||
impl<T: Hash> Hash for AtomicShared<T> {
|
||||
impl<T: Hash> Hash for Shared<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.borrow_mut().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Default for AtomicShared<T> {
|
||||
impl<T: Default> Default for Shared<T> {
|
||||
fn default() -> Self {
|
||||
Self::new(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display> fmt::Display for AtomicShared<T> {
|
||||
impl<T: fmt::Display> fmt::Display for Shared<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.borrow_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AtomicShared<T> {
|
||||
impl<T> Shared<T> {
|
||||
pub fn new(t: T) -> Self {
|
||||
Self(Arc::new(Mutex::new(t)))
|
||||
Self(Arc::new(RwLock::new(t)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -160,27 +163,56 @@ impl<T> AtomicShared<T> {
|
|||
Ok(mutex) => mutex,
|
||||
Err(_rc) => panic!("unwrapping failed"),
|
||||
};
|
||||
Mutex::into_inner(mutex).unwrap()
|
||||
RwLock::into_inner(mutex)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> AtomicShared<T> {
|
||||
impl<T: ?Sized> Shared<T> {
|
||||
#[inline]
|
||||
pub fn copy(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn borrow_mut(&self) -> MutexGuard<'_, T> {
|
||||
self.0.lock().unwrap()
|
||||
pub fn borrow(&self) -> RwLockReadGuard<'_, T> {
|
||||
println!("borrowing {}", std::any::type_name::<T>());
|
||||
let res = self.0.read();
|
||||
println!("borrowed successfully");
|
||||
res
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn borrow_mut(&self) -> RwLockWriteGuard<'_, T> {
|
||||
println!("borrowing mut {}", std::any::type_name::<T>());
|
||||
let res = self.0.write();
|
||||
println!("borrowed mut successfully");
|
||||
res
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self) -> Option<&mut T> {
|
||||
Arc::get_mut(&mut self.0).map(|mutex| mutex.get_mut().unwrap())
|
||||
Arc::get_mut(&mut self.0).map(|mutex| mutex.get_mut())
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *mut T {
|
||||
Arc::as_ptr(&self.0) as *mut T
|
||||
}
|
||||
|
||||
pub fn can_borrow(&self) -> bool {
|
||||
self.0.try_read().is_some()
|
||||
}
|
||||
|
||||
pub fn can_borrow_mut(&self) -> bool {
|
||||
self.0.try_write().is_some()
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// don't call this except you need to handle cyclic references.
|
||||
pub unsafe fn force_unlock_write(&self) {
|
||||
self.0.force_unlock_write();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> AtomicShared<T> {
|
||||
impl<T: Clone> Shared<T> {
|
||||
#[inline]
|
||||
pub fn clone_inner(&self) -> T {
|
||||
self.borrow_mut().clone()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::cell::RefCell;
|
||||
use std::thread::LocalKey;
|
||||
// use std::cell::RefCell;
|
||||
// use std::thread::LocalKey;
|
||||
|
||||
#[cfg(not(feature = "full-repl"))]
|
||||
use std::io::{stdin, BufRead, BufReader};
|
||||
|
@ -261,57 +261,52 @@ impl StdinReader {
|
|||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static READER: RefCell<StdinReader> = RefCell::new(StdinReader{
|
||||
static READER: crate::shared::RwLock<StdinReader> = crate::shared::RwLock::new(StdinReader {
|
||||
block_begin: 1,
|
||||
lineno: 1,
|
||||
buf: vec![],
|
||||
#[cfg(feature = "full-repl")]
|
||||
history_input_position: 1,
|
||||
indent: 1
|
||||
indent: 1,
|
||||
});
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GlobalStdin(LocalKey<RefCell<StdinReader>>);
|
||||
pub struct GlobalStdin(&'static crate::shared::RwLock<StdinReader>);
|
||||
|
||||
pub static GLOBAL_STDIN: GlobalStdin = GlobalStdin(READER);
|
||||
pub static GLOBAL_STDIN: GlobalStdin = GlobalStdin(&READER);
|
||||
|
||||
impl GlobalStdin {
|
||||
pub fn read(&'static self) -> String {
|
||||
self.0.with(|s| s.borrow_mut().read())
|
||||
self.0.write().read()
|
||||
}
|
||||
|
||||
pub fn reread(&'static self) -> String {
|
||||
self.0.with(|s| s.borrow().reread())
|
||||
self.0.read().reread()
|
||||
}
|
||||
|
||||
pub fn reread_lines(&'static self, ln_begin: usize, ln_end: usize) -> Vec<String> {
|
||||
self.0
|
||||
.with(|s| s.borrow_mut().reread_lines(ln_begin, ln_end))
|
||||
self.0.read().reread_lines(ln_begin, ln_end)
|
||||
}
|
||||
|
||||
pub fn lineno(&'static self) -> usize {
|
||||
self.0.with(|s| s.borrow().lineno)
|
||||
self.0.read().lineno
|
||||
}
|
||||
|
||||
pub fn block_begin(&'static self) -> usize {
|
||||
self.0.with(|s| s.borrow().block_begin)
|
||||
self.0.read().block_begin
|
||||
}
|
||||
|
||||
pub fn set_block_begin(&'static self, n: usize) {
|
||||
self.0.with(|s| s.borrow_mut().block_begin = n);
|
||||
self.0.write().block_begin = n;
|
||||
}
|
||||
|
||||
pub fn set_indent(&'static self, n: usize) {
|
||||
self.0.with(|s| s.borrow_mut().indent = n as u16);
|
||||
self.0.write().indent = n as u16;
|
||||
}
|
||||
|
||||
pub fn insert_whitespace(&'static self, whitespace: &str) {
|
||||
self.0.with(|s| {
|
||||
if let Some(line) = s.borrow_mut().last_line() {
|
||||
if let Some(line) = self.0.write().last_line() {
|
||||
line.insert_str(0, whitespace);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::ty::codeobj::{CodeObj, CodeObjFlags, MakeFunctionFlags};
|
|||
use crate::ty::value::GenTypeObj;
|
||||
use erg_common::cache::CacheSet;
|
||||
use erg_common::config::{ErgConfig, Input};
|
||||
use erg_common::env::erg_std_path;
|
||||
use erg_common::env::ERG_STD_PATH;
|
||||
use erg_common::error::{ErrorDisplay, Location};
|
||||
use erg_common::opcode::{CommonOpcode, CompareOp};
|
||||
use erg_common::opcode308::Opcode308;
|
||||
|
@ -3120,7 +3120,7 @@ impl PyCodeGenerator {
|
|||
);
|
||||
self.emit_load_name_instr(Identifier::private("#path"));
|
||||
self.emit_load_method_instr(Identifier::public("append"));
|
||||
self.emit_load_const(erg_std_path().to_str().unwrap());
|
||||
self.emit_load_const(ERG_STD_PATH.to_str().unwrap());
|
||||
self.emit_call_instr(1, Method);
|
||||
self.stack_dec();
|
||||
self.emit_pop_top();
|
||||
|
|
|
@ -15,6 +15,7 @@ use std::path::PathBuf;
|
|||
use erg_common::config::ErgConfig;
|
||||
use erg_common::consts::{DEBUG_MODE, ERG_MODE, PYTHON_MODE};
|
||||
use erg_common::dict;
|
||||
use erg_common::env::{ERG_PYSTD_PATH, ERG_STD_DECL_PATH};
|
||||
use erg_common::error::Location;
|
||||
use erg_common::fresh::fresh_varname;
|
||||
#[allow(unused_imports)]
|
||||
|
@ -513,11 +514,11 @@ const KW_OFFSET: &str = "offset";
|
|||
const KW_WHENCE: &str = "whence";
|
||||
|
||||
pub fn builtins_path() -> PathBuf {
|
||||
erg_common::env::erg_pystd_path().join("builtins.d.er")
|
||||
ERG_PYSTD_PATH.join("builtins.d.er")
|
||||
}
|
||||
|
||||
pub fn std_decl_path() -> PathBuf {
|
||||
erg_common::env::erg_std_decl_path()
|
||||
ERG_STD_DECL_PATH.clone()
|
||||
}
|
||||
|
||||
impl Context {
|
||||
|
@ -772,7 +773,8 @@ impl Context {
|
|||
);
|
||||
self.consts.insert(name.clone(), val);
|
||||
for impl_trait in ctx.super_traits.iter() {
|
||||
if let Some(impls) = self.trait_impls().get_mut(&impl_trait.qual_name()) {
|
||||
if self.trait_impls().get(&impl_trait.qual_name()).is_some() {
|
||||
let mut impls = self.trait_impls().get_mut(&impl_trait.qual_name());
|
||||
impls.insert(TraitImpl::new(t.clone(), impl_trait.clone()));
|
||||
} else {
|
||||
self.trait_impls().register(
|
||||
|
@ -848,7 +850,8 @@ impl Context {
|
|||
}
|
||||
self.consts.insert(name.clone(), val);
|
||||
for impl_trait in ctx.super_traits.iter() {
|
||||
if let Some(impls) = self.trait_impls().get_mut(&impl_trait.qual_name()) {
|
||||
if self.trait_impls().get(&impl_trait.qual_name()).is_some() {
|
||||
let mut impls = self.trait_impls().get_mut(&impl_trait.qual_name());
|
||||
impls.insert(TraitImpl::new(t.clone(), impl_trait.clone()));
|
||||
} else {
|
||||
self.trait_impls().register(
|
||||
|
@ -912,7 +915,12 @@ impl Context {
|
|||
}
|
||||
}
|
||||
if let ContextKind::GluePatch(tr_impl) = &ctx.kind {
|
||||
if let Some(impls) = self.trait_impls().get_mut(&tr_impl.sup_trait.qual_name()) {
|
||||
if self
|
||||
.trait_impls()
|
||||
.get(&tr_impl.sup_trait.qual_name())
|
||||
.is_some()
|
||||
{
|
||||
let mut impls = self.trait_impls().get_mut(&tr_impl.sup_trait.qual_name());
|
||||
impls.insert(tr_impl.clone());
|
||||
} else {
|
||||
self.trait_impls()
|
||||
|
|
|
@ -1653,7 +1653,8 @@ impl Context {
|
|||
self.decls.insert(name.clone(), vi);
|
||||
self.consts.insert(name.clone(), val);
|
||||
for impl_trait in ctx.super_traits.iter() {
|
||||
if let Some(impls) = self.trait_impls().get_mut(&impl_trait.qual_name()) {
|
||||
if self.trait_impls().get(&impl_trait.qual_name()).is_some() {
|
||||
let mut impls = self.trait_impls().get_mut(&impl_trait.qual_name());
|
||||
impls.insert(TraitImpl::new(t.clone(), impl_trait.clone()));
|
||||
} else {
|
||||
self.trait_impls().register(
|
||||
|
@ -1733,7 +1734,8 @@ impl Context {
|
|||
self.consts
|
||||
.insert(name.clone(), ValueObj::Type(TypeObj::Generated(gen)));
|
||||
for impl_trait in ctx.super_traits.iter() {
|
||||
if let Some(impls) = self.trait_impls().get_mut(&impl_trait.qual_name()) {
|
||||
if self.trait_impls().get(&impl_trait.qual_name()).is_some() {
|
||||
let mut impls = self.trait_impls().get_mut(&impl_trait.qual_name());
|
||||
impls.insert(TraitImpl::new(t.clone(), impl_trait.clone()));
|
||||
} else {
|
||||
self.trait_impls().register(
|
||||
|
|
|
@ -1892,12 +1892,18 @@ impl ASTLowerer {
|
|||
trait_loc: &impl Locational,
|
||||
) -> LowerResult<()> {
|
||||
// TODO: polymorphic trait
|
||||
if let Some(impls) = self
|
||||
if self
|
||||
.module
|
||||
.context
|
||||
.trait_impls()
|
||||
.get_mut(&trait_.qual_name())
|
||||
.get(&trait_.qual_name())
|
||||
.is_some()
|
||||
{
|
||||
let mut impls = self
|
||||
.module
|
||||
.context
|
||||
.trait_impls()
|
||||
.get_mut(&trait_.qual_name());
|
||||
impls.insert(TraitImpl::new(class.clone(), trait_.clone()));
|
||||
} else {
|
||||
self.module.context.trait_impls().register(
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::borrow::Borrow;
|
|||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use erg_common::config::ErgConfig;
|
||||
use erg_common::dict::Dict;
|
||||
|
@ -32,7 +32,7 @@ impl ModId {
|
|||
pub struct ModuleEntry {
|
||||
pub id: ModId, // builtin == 0, __main__ == 1
|
||||
pub hir: Option<HIR>,
|
||||
pub module: Rc<ModuleContext>,
|
||||
pub module: Arc<ModuleContext>,
|
||||
}
|
||||
|
||||
impl fmt::Display for ModuleEntry {
|
||||
|
@ -50,7 +50,7 @@ impl ModuleEntry {
|
|||
Self {
|
||||
id,
|
||||
hir,
|
||||
module: Rc::new(ctx),
|
||||
module: Arc::new(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ impl ModuleEntry {
|
|||
Self {
|
||||
id: ModId::builtin(),
|
||||
hir: None,
|
||||
module: Rc::new(ctx),
|
||||
module: Arc::new(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ impl SharedModuleCache {
|
|||
ref_.get_mut(path)
|
||||
}
|
||||
|
||||
pub fn get_ctx<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> Option<Rc<ModuleContext>>
|
||||
pub fn get_ctx<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> Option<Arc<ModuleContext>>
|
||||
where
|
||||
PathBuf: Borrow<Q>,
|
||||
{
|
||||
|
@ -236,7 +236,7 @@ impl SharedModuleCache {
|
|||
for path in self.keys() {
|
||||
self.remove(&path);
|
||||
}
|
||||
self.register(builtin_path, None, Rc::try_unwrap(builtin.module).unwrap());
|
||||
self.register(builtin_path, None, Arc::try_unwrap(builtin.module).unwrap());
|
||||
}
|
||||
|
||||
pub fn rename_path(&self, path: &PathBuf, new: PathBuf) {
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::hash::Hash;
|
|||
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::set::Set;
|
||||
use erg_common::shared::Shared;
|
||||
use erg_common::shared::{MappedRwLockWriteGuard, RwLockWriteGuard, Shared};
|
||||
use erg_common::Str;
|
||||
|
||||
use crate::context::TraitImpl;
|
||||
|
@ -84,12 +84,13 @@ impl SharedTraitImpls {
|
|||
ref_.get(path)
|
||||
}
|
||||
|
||||
pub fn get_mut<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> Option<&mut Set<TraitImpl>>
|
||||
pub fn get_mut<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> MappedRwLockWriteGuard<Set<TraitImpl>>
|
||||
where
|
||||
Str: Borrow<Q>,
|
||||
{
|
||||
let ref_ = unsafe { self.0.as_ptr().as_mut().unwrap() };
|
||||
ref_.get_mut(path)
|
||||
// let ref_ = unsafe { self.0.as_ptr().as_mut().unwrap() };
|
||||
// ref_.get_mut(path)
|
||||
RwLockWriteGuard::map(self.0.borrow_mut(), |tis| tis.get_mut(path).unwrap())
|
||||
}
|
||||
|
||||
pub fn register(&self, name: Str, impls: Set<TraitImpl>) {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use std::cell::{Ref, RefMut};
|
||||
// use std::cell::{Ref, RefMut};
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::mem;
|
||||
|
||||
use erg_common::fresh::VAR_ID;
|
||||
use erg_common::shared::Shared;
|
||||
use erg_common::traits::{LimitedDisplay, StructuralEq};
|
||||
use erg_common::Str;
|
||||
|
@ -17,10 +18,6 @@ pub type Id = usize;
|
|||
/// HACK: see doc/compiler/inference.md for details
|
||||
pub const GENERIC_LEVEL: usize = usize::MAX;
|
||||
|
||||
thread_local! {
|
||||
static UNBOUND_ID: Shared<usize> = Shared::new(0);
|
||||
}
|
||||
|
||||
pub trait HasLevel {
|
||||
fn level(&self) -> Option<Level>;
|
||||
fn set_level(&self, lev: Level);
|
||||
|
@ -429,14 +426,12 @@ impl<T> FreeKind<T> {
|
|||
}
|
||||
|
||||
pub fn new_unbound(lev: Level, constraint: Constraint) -> Self {
|
||||
UNBOUND_ID.with(|id| {
|
||||
*id.borrow_mut() += 1;
|
||||
*VAR_ID.borrow_mut() += 1;
|
||||
Self::Unbound {
|
||||
id: *id.borrow(),
|
||||
id: *VAR_ID.borrow(),
|
||||
lev,
|
||||
constraint,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub const fn named_unbound(name: Str, lev: Level, constraint: Constraint) -> Self {
|
||||
|
@ -601,10 +596,10 @@ impl<T: LimitedDisplay> LimitedDisplay for Free<T> {
|
|||
}
|
||||
|
||||
impl<T> Free<T> {
|
||||
pub fn borrow(&self) -> Ref<'_, FreeKind<T>> {
|
||||
pub fn borrow(&self) -> erg_common::shared::RwLockReadGuard<'_, FreeKind<T>> {
|
||||
self.0.borrow()
|
||||
}
|
||||
pub fn borrow_mut(&self) -> RefMut<'_, FreeKind<T>> {
|
||||
pub fn borrow_mut(&self) -> erg_common::shared::RwLockWriteGuard<'_, FreeKind<T>> {
|
||||
self.0.borrow_mut()
|
||||
}
|
||||
/// very unsafe, use `force_replace` instead whenever possible
|
||||
|
@ -620,8 +615,9 @@ impl<T> Free<T> {
|
|||
return;
|
||||
}
|
||||
unsafe {
|
||||
*self.0.as_ptr() = new;
|
||||
self.0.force_unlock_write();
|
||||
}
|
||||
*self.0.borrow_mut() = new;
|
||||
}
|
||||
pub fn can_borrow(&self) -> bool {
|
||||
self.0.can_borrow()
|
||||
|
@ -650,7 +646,7 @@ impl Free<TyParam> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: StructuralEq + CanbeFree + Clone + Default> StructuralEq for Free<T> {
|
||||
impl<T: StructuralEq + CanbeFree + Clone + Default + fmt::Debug> StructuralEq for Free<T> {
|
||||
fn structural_eq(&self, other: &Self) -> bool {
|
||||
if let (Some((l, r)), Some((l2, r2))) = (self.get_subsup(), other.get_subsup()) {
|
||||
self.dummy_link();
|
||||
|
@ -736,14 +732,12 @@ impl<T> Free<T> {
|
|||
}
|
||||
|
||||
pub fn new_unbound(level: Level, constraint: Constraint) -> Self {
|
||||
UNBOUND_ID.with(|id| {
|
||||
*id.borrow_mut() += 1;
|
||||
*VAR_ID.borrow_mut() += 1;
|
||||
Self(Shared::new(FreeKind::unbound(
|
||||
*id.borrow(),
|
||||
*VAR_ID.borrow(),
|
||||
level,
|
||||
constraint,
|
||||
)))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_named_unbound(name: Str, level: Level, constraint: Constraint) -> Self {
|
||||
|
@ -766,8 +760,8 @@ impl<T> Free<T> {
|
|||
|
||||
/// returns linked type (panic if self is unbounded)
|
||||
/// NOTE: check by `.is_linked` before call
|
||||
pub fn crack(&self) -> Ref<'_, T> {
|
||||
Ref::map(self.borrow(), |f| match f {
|
||||
pub fn crack(&self) -> erg_common::shared::MappedRwLockReadGuard<'_, T> {
|
||||
erg_common::shared::RwLockReadGuard::map(self.borrow(), |f| match f {
|
||||
FreeKind::Linked(t) | FreeKind::UndoableLinked { t, .. } => t,
|
||||
FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => {
|
||||
panic!("the value is unbounded")
|
||||
|
@ -775,8 +769,8 @@ impl<T> Free<T> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn crack_constraint(&self) -> Ref<'_, Constraint> {
|
||||
Ref::map(self.borrow(), |f| match f {
|
||||
pub fn crack_constraint(&self) -> erg_common::shared::MappedRwLockReadGuard<'_, Constraint> {
|
||||
erg_common::shared::RwLockReadGuard::map(self.borrow(), |f| match f {
|
||||
FreeKind::Linked(_) | FreeKind::UndoableLinked { .. } => panic!("the value is linked"),
|
||||
FreeKind::Unbound { constraint, .. } | FreeKind::NamedUnbound { constraint, .. } => {
|
||||
constraint
|
||||
|
@ -814,7 +808,7 @@ impl<T> Free<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> Free<T> {
|
||||
impl<T: Clone + fmt::Debug> Free<T> {
|
||||
/// SAFETY: use `Type/TyParam::link` instead of this.
|
||||
/// This method may cause circular references.
|
||||
pub(super) fn link(&self, to: &T) {
|
||||
|
@ -871,7 +865,7 @@ impl<T: Clone> Free<T> {
|
|||
let prev = *previous.clone();
|
||||
self.force_replace(prev);
|
||||
}
|
||||
_other => panic!("cannot undo"),
|
||||
_other => panic!("cannot undo: {_other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -920,7 +914,7 @@ impl<T: Clone> Free<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Default + Clone> Free<T> {
|
||||
impl<T: Default + Clone + fmt::Debug> Free<T> {
|
||||
pub fn dummy_link(&self) {
|
||||
self.forced_undoable_link(&T::default());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue