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