mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 12:14:43 +00:00
chore(els): let FileCache: Send + Sync
This commit is contained in:
parent
591440333a
commit
c84294fc11
15 changed files with 101 additions and 88 deletions
|
@ -353,9 +353,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
// TODO: multiline comments
|
// TODO: multiline comments
|
||||||
if self
|
if self
|
||||||
.file_cache
|
.file_cache
|
||||||
.get(&uri)
|
.get_line(&uri, pos.line)
|
||||||
.unwrap()
|
|
||||||
.get_line(pos.line)
|
|
||||||
.map_or(false, |line| line.starts_with('#'))
|
.map_or(false, |line| line.starts_with('#'))
|
||||||
{
|
{
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
let dependents = self.dependents_of(&uri);
|
let dependents = self.dependents_of(&uri);
|
||||||
for dep in dependents {
|
for dep in dependents {
|
||||||
// _log!("dep: {dep}");
|
// _log!("dep: {dep}");
|
||||||
let code = self.file_cache.get_code(&dep)?.to_string();
|
let code = self.file_cache.get_entire_code(&dep)?.to_string();
|
||||||
self.check_file(dep, code)?;
|
self.check_file(dep, code)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -76,19 +76,19 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
let Some(ts) = self.file_cache.get_token_stream(&uri) else {
|
let Some(ts) = self.file_cache.get_token_stream(&uri) else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
let mut parser = Parser::new(ts.clone());
|
let mut parser = Parser::new(ts);
|
||||||
if parser.parse().is_err() {
|
if parser.parse().is_err() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let path = util::uri_to_path(&uri);
|
let path = util::uri_to_path(&uri);
|
||||||
let code = &self.file_cache.get(&uri).unwrap().code;
|
let code = self.file_cache.get_entire_code(&uri)?;
|
||||||
let mode = if path.to_string_lossy().ends_with(".d.er") {
|
let mode = if path.to_string_lossy().ends_with(".d.er") {
|
||||||
"declare"
|
"declare"
|
||||||
} else {
|
} else {
|
||||||
"exec"
|
"exec"
|
||||||
};
|
};
|
||||||
let mut checker = self.get_checker(path);
|
let mut checker = self.get_checker(path);
|
||||||
match checker.build(code.into(), mode) {
|
match checker.build(code, mode) {
|
||||||
Ok(artifact) => {
|
Ok(artifact) => {
|
||||||
self.artifacts.insert(uri.clone(), artifact.into());
|
self.artifacts.insert(uri.clone(), artifact.into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use lsp_types::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use erg_common::dict::Dict;
|
use erg_common::dict::Dict;
|
||||||
use erg_common::shared::Shared;
|
use erg_common::shared::AtomicShared;
|
||||||
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};
|
||||||
|
@ -37,9 +37,9 @@ pub struct FileCacheEntry {
|
||||||
|
|
||||||
impl FileCacheEntry {
|
impl FileCacheEntry {
|
||||||
/// line: 0-based
|
/// line: 0-based
|
||||||
pub fn get_line(&self, line: u32) -> Option<&str> {
|
pub fn get_line(&self, line: u32) -> Option<String> {
|
||||||
let mut lines = self.code.lines();
|
let mut lines = self.code.lines();
|
||||||
lines.nth(line as usize)
|
lines.nth(line as usize).map(|s| s.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,16 +47,25 @@ 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: Shared<Dict<NormalizedUrl, FileCacheEntry>>,
|
pub files: AtomicShared<Dict<NormalizedUrl, FileCacheEntry>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileCache {
|
impl FileCache {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
files: Shared::new(Dict::new()),
|
files: AtomicShared::new(Dict::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_once(&self, uri: &NormalizedUrl) -> ELSResult<()> {
|
||||||
|
if self.files.borrow_mut().get(uri).is_some() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let code = _get_code_from_uri(uri)?;
|
||||||
|
self.update(uri, code, None);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn set_capabilities(&mut self, capabilities: &mut ServerCapabilities) {
|
pub(crate) fn set_capabilities(&mut self, capabilities: &mut ServerCapabilities) {
|
||||||
let workspace_folders = WorkspaceFoldersServerCapabilities {
|
let workspace_folders = WorkspaceFoldersServerCapabilities {
|
||||||
supported: Some(true),
|
supported: Some(true),
|
||||||
|
@ -98,36 +107,28 @@ impl FileCache {
|
||||||
capabilities.text_document_sync = Some(TextDocumentSyncCapability::Options(sync_option));
|
capabilities.text_document_sync = Some(TextDocumentSyncCapability::Options(sync_option));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_code(&self, uri: &NormalizedUrl) -> ELSResult<&str> {
|
/// This method clones and returns the entire file.
|
||||||
Ok(self.get(uri)?.code.as_str())
|
/// If you only need part of the file, use `get_ranged` or `get_line` instead.
|
||||||
|
pub fn get_entire_code(&self, uri: &NormalizedUrl) -> ELSResult<String> {
|
||||||
|
self.load_once(uri)?;
|
||||||
|
Ok(self
|
||||||
|
.files
|
||||||
|
.borrow_mut()
|
||||||
|
.get(uri)
|
||||||
|
.ok_or("not found")?
|
||||||
|
.code
|
||||||
|
.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, uri: &NormalizedUrl) -> ELSResult<&FileCacheEntry> {
|
pub fn get_token_stream(&self, uri: &NormalizedUrl) -> Option<TokenStream> {
|
||||||
let Some(entry) = unsafe { self.files.as_ref() }.get(uri) else {
|
let _ = self.load_once(uri);
|
||||||
let code = _get_code_from_uri(uri)?;
|
self.files.borrow_mut().get(uri)?.token_stream.clone()
|
||||||
self.update(uri, code, None);
|
|
||||||
let entry = unsafe { self.files.as_ref() }.get(uri).ok_or("not found")?;
|
|
||||||
return Ok(entry);
|
|
||||||
};
|
|
||||||
Ok(entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_token_stream(&self, uri: &NormalizedUrl) -> Option<&TokenStream> {
|
|
||||||
self.get(uri).ok().and_then(|ent| ent.token_stream.as_ref())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_token_index(&self, uri: &NormalizedUrl, pos: Position) -> Option<usize> {
|
|
||||||
let tokens = self.get_token_stream(uri)?;
|
|
||||||
for (i, tok) in tokens.iter().enumerate() {
|
|
||||||
if util::pos_in_loc(tok, pos) {
|
|
||||||
return Some(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_token(&self, uri: &NormalizedUrl, pos: Position) -> Option<Token> {
|
pub fn get_token(&self, uri: &NormalizedUrl, pos: Position) -> Option<Token> {
|
||||||
let tokens = self.get_token_stream(uri)?;
|
let _ = self.load_once(uri);
|
||||||
|
let ent = self.files.borrow_mut();
|
||||||
|
let tokens = ent.get(uri)?.token_stream.as_ref()?;
|
||||||
for tok in tokens.iter() {
|
for tok in tokens.iter() {
|
||||||
if util::pos_in_loc(tok, pos) {
|
if util::pos_in_loc(tok, pos) {
|
||||||
return Some(tok.clone());
|
return Some(tok.clone());
|
||||||
|
@ -142,8 +143,17 @@ impl FileCache {
|
||||||
pos: Position,
|
pos: Position,
|
||||||
offset: isize,
|
offset: isize,
|
||||||
) -> Option<Token> {
|
) -> Option<Token> {
|
||||||
let tokens = self.get_token_stream(uri)?;
|
let _ = self.load_once(uri);
|
||||||
let index = self.get_token_index(uri, pos)?;
|
let ent = self.files.borrow_mut();
|
||||||
|
let tokens = ent.get(uri)?.token_stream.as_ref()?;
|
||||||
|
let index = (|| {
|
||||||
|
for (i, tok) in tokens.iter().enumerate() {
|
||||||
|
if util::pos_in_loc(tok, pos) {
|
||||||
|
return Some(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
})()?;
|
||||||
let index = (index as isize + offset) as usize;
|
let index = (index as isize + offset) as usize;
|
||||||
if index < tokens.len() {
|
if index < tokens.len() {
|
||||||
Some(tokens[index].clone())
|
Some(tokens[index].clone())
|
||||||
|
@ -153,8 +163,9 @@ impl FileCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 0-based
|
/// 0-based
|
||||||
pub(crate) fn get_line(&self, uri: &NormalizedUrl, line: u32) -> Option<&str> {
|
pub(crate) fn get_line(&self, uri: &NormalizedUrl, line: u32) -> Option<String> {
|
||||||
self.get(uri).ok().and_then(|ent| ent.get_line(line))
|
let _ = self.load_once(uri);
|
||||||
|
self.files.borrow_mut().get(uri)?.get_line(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_ranged(
|
pub(crate) fn get_ranged(
|
||||||
|
@ -162,7 +173,9 @@ impl FileCache {
|
||||||
uri: &NormalizedUrl,
|
uri: &NormalizedUrl,
|
||||||
range: Range,
|
range: Range,
|
||||||
) -> ELSResult<Option<String>> {
|
) -> ELSResult<Option<String>> {
|
||||||
let file = self.get(uri)?;
|
self.load_once(uri)?;
|
||||||
|
let ent = self.files.borrow_mut();
|
||||||
|
let file = ent.get(uri).ok_or("not found")?;
|
||||||
let mut code = String::new();
|
let mut code = String::new();
|
||||||
for (i, line) in file.code.lines().enumerate() {
|
for (i, line) in file.code.lines().enumerate() {
|
||||||
if i >= range.start.line as usize && i <= range.end.line as usize {
|
if i >= range.start.line as usize && i <= range.end.line as usize {
|
||||||
|
@ -191,7 +204,8 @@ impl FileCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn update(&self, uri: &NormalizedUrl, code: String, ver: Option<i32>) {
|
pub(crate) fn update(&self, uri: &NormalizedUrl, code: String, ver: Option<i32>) {
|
||||||
let entry = unsafe { self.files.as_ref() }.get(uri);
|
let ent = self.files.borrow_mut();
|
||||||
|
let entry = ent.get(uri);
|
||||||
if let Some(entry) = entry {
|
if let Some(entry) = entry {
|
||||||
if ver.map_or(false, |ver| ver <= entry.ver) {
|
if ver.map_or(false, |ver| ver <= entry.ver) {
|
||||||
// crate::_log!("171: double update detected: {ver:?}, {}, code:\n{}", entry.ver, entry.code);
|
// crate::_log!("171: double update detected: {ver:?}, {}, code:\n{}", entry.ver, entry.code);
|
||||||
|
@ -206,6 +220,7 @@ impl FileCache {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
drop(ent);
|
||||||
self.files.borrow_mut().insert(
|
self.files.borrow_mut().insert(
|
||||||
uri.clone(),
|
uri.clone(),
|
||||||
FileCacheEntry {
|
FileCacheEntry {
|
||||||
|
@ -217,7 +232,8 @@ impl FileCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn ranged_update(&self, uri: &NormalizedUrl, old: Range, new_code: &str) {
|
pub(crate) fn ranged_update(&self, uri: &NormalizedUrl, old: Range, new_code: &str) {
|
||||||
let Some(entry) = unsafe { self.files.as_mut() }.get_mut(uri) else {
|
let mut ent = self.files.borrow_mut();
|
||||||
|
let Some(entry) = ent.get_mut(uri) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let mut code = entry.code.clone();
|
let mut code = entry.code.clone();
|
||||||
|
@ -232,7 +248,8 @@ impl FileCache {
|
||||||
|
|
||||||
pub(crate) fn incremental_update(&self, params: DidChangeTextDocumentParams) {
|
pub(crate) fn incremental_update(&self, params: DidChangeTextDocumentParams) {
|
||||||
let uri = NormalizedUrl::new(params.text_document.uri);
|
let uri = NormalizedUrl::new(params.text_document.uri);
|
||||||
let Some(entry) = unsafe { self.files.as_mut() }.get_mut(&uri) else {
|
let mut ent = self.files.borrow_mut();
|
||||||
|
let Some(entry) = ent.get_mut(&uri) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if entry.ver >= params.text_document.version {
|
if entry.ver >= params.text_document.version {
|
||||||
|
|
|
@ -230,7 +230,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
};
|
};
|
||||||
let mut prev_token = Token::DUMMY;
|
let mut prev_token = Token::DUMMY;
|
||||||
loop {
|
loop {
|
||||||
let Some(token) = util::get_token_from_stream(stream, def_pos)? else {
|
let Some(token) = util::get_token_from_stream(&stream, def_pos)? else {
|
||||||
next!(def_pos, default_code_block, contents);
|
next!(def_pos, default_code_block, contents);
|
||||||
};
|
};
|
||||||
if token.deep_eq(&prev_token) {
|
if token.deep_eq(&prev_token) {
|
||||||
|
|
|
@ -91,7 +91,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
}
|
}
|
||||||
// recheck dependencies and finally the file itself
|
// recheck dependencies and finally the file itself
|
||||||
for dep in dependencies {
|
for dep in dependencies {
|
||||||
let code = self.file_cache.get_code(&dep)?.to_string();
|
let code = self.file_cache.get_entire_code(&dep)?.to_string();
|
||||||
self.check_file(dep, code)?;
|
self.check_file(dep, code)?;
|
||||||
}
|
}
|
||||||
// dependents are checked after changes are committed
|
// dependents are checked after changes are committed
|
||||||
|
|
|
@ -290,9 +290,9 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
send_log(format!("full semantic tokens request: {params:?}"))?;
|
send_log(format!("full semantic tokens request: {params:?}"))?;
|
||||||
let uri = NormalizedUrl::new(params.text_document.uri);
|
let uri = NormalizedUrl::new(params.text_document.uri);
|
||||||
let path = util::uri_to_path(&uri);
|
let path = util::uri_to_path(&uri);
|
||||||
let src = self.file_cache.get_code(&uri)?;
|
let src = self.file_cache.get_entire_code(&uri)?;
|
||||||
let mut builder = ASTBuilder::new(self.cfg.inherit(path));
|
let mut builder = ASTBuilder::new(self.cfg.inherit(path));
|
||||||
let result = match builder.build_without_desugaring(src.to_string()) {
|
let result = match builder.build_without_desugaring(src) {
|
||||||
Ok(ast) => {
|
Ok(ast) => {
|
||||||
let mut state = ASTSemanticState::new();
|
let mut state = ASTSemanticState::new();
|
||||||
let tokens = state.enumerate_tokens(ast);
|
let tokens = state.enumerate_tokens(ast);
|
||||||
|
|
|
@ -507,7 +507,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
let uri =
|
let uri =
|
||||||
NormalizedUrl::parse(msg["params"]["textDocument"]["uri"].as_str().unwrap())?;
|
NormalizedUrl::parse(msg["params"]["textDocument"]["uri"].as_str().unwrap())?;
|
||||||
send_log(format!("{method}: {uri}"))?;
|
send_log(format!("{method}: {uri}"))?;
|
||||||
let code = self.file_cache.get_code(&uri)?.to_string();
|
let code = self.file_cache.get_entire_code(&uri)?;
|
||||||
self.clear_cache(&uri);
|
self.clear_cache(&uri);
|
||||||
self.check_file(uri, code)
|
self.check_file(uri, code)
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,11 +86,9 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
args_loc: erg_common::error::Location,
|
args_loc: erg_common::error::Location,
|
||||||
token: &Token,
|
token: &Token,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
|
let tks = self.file_cache.get_token_stream(uri).unwrap();
|
||||||
// we should use the latest commas
|
// we should use the latest commas
|
||||||
let commas = self
|
let commas = tks
|
||||||
.file_cache
|
|
||||||
.get_token_stream(uri)
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
.iter()
|
||||||
.skip_while(|&tk| tk.loc() < args_loc)
|
.skip_while(|&tk| tk.loc() < args_loc)
|
||||||
.filter(|tk| tk.is(TokenKind::Comma) && args_loc.ln_end() >= tk.ln_begin())
|
.filter(|tk| tk.is(TokenKind::Comma) && args_loc.ln_end() >= tk.ln_begin())
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
use std::borrow::{Borrow, ToOwned};
|
use std::borrow::{Borrow, ToOwned};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::rc::Rc;
|
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::{RcArray, Str};
|
use crate::{ArcArray, Str};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CacheSet<T: ?Sized>(RefCell<Set<Rc<T>>>);
|
pub struct CacheSet<T: ?Sized>(RefCell<Set<Arc<T>>>);
|
||||||
|
|
||||||
impl<T: ?Sized> Default for CacheSet<T> {
|
impl<T: ?Sized> Default for CacheSet<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
@ -47,31 +47,31 @@ impl CacheSet<str> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Hash + Eq + Clone> CacheSet<[T]> {
|
impl<T: Hash + Eq + Clone> CacheSet<[T]> {
|
||||||
pub fn get(&self, q: &[T]) -> Rc<[T]> {
|
pub fn get(&self, q: &[T]) -> Arc<[T]> {
|
||||||
if let Some(cached) = self.0.borrow().get(q) {
|
if let Some(cached) = self.0.borrow().get(q) {
|
||||||
return cached.clone();
|
return cached.clone();
|
||||||
} // &self.0 is dropped
|
} // &self.0 is dropped
|
||||||
let s = RcArray::from(q);
|
let s = ArcArray::from(q);
|
||||||
self.0.borrow_mut().insert(s.clone());
|
self.0.borrow_mut().insert(s.clone());
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Hash + Eq> CacheSet<T> {
|
impl<T: Hash + Eq> CacheSet<T> {
|
||||||
pub fn get<Q: ?Sized + Hash + Eq>(&self, q: &Q) -> Rc<T>
|
pub fn get<Q: ?Sized + Hash + Eq>(&self, q: &Q) -> Arc<T>
|
||||||
where
|
where
|
||||||
Rc<T>: Borrow<Q>,
|
Arc<T>: Borrow<Q>,
|
||||||
Q: ToOwned<Owned = T>,
|
Q: ToOwned<Owned = T>,
|
||||||
{
|
{
|
||||||
if let Some(cached) = self.0.borrow().get(q) {
|
if let Some(cached) = self.0.borrow().get(q) {
|
||||||
return cached.clone();
|
return cached.clone();
|
||||||
} // &self.0 is dropped
|
} // &self.0 is dropped
|
||||||
let s = Rc::from(q.to_owned());
|
let s = Arc::from(q.to_owned());
|
||||||
self.0.borrow_mut().insert(s.clone());
|
self.0.borrow_mut().insert(s.clone());
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CacheDict<K, V: ?Sized>(RefCell<Dict<K, Rc<V>>>);
|
pub struct CacheDict<K, V: ?Sized>(RefCell<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<RefCell<CacheDict<K, V>>>);
|
||||||
|
|
|
@ -39,7 +39,7 @@ use crate::set::Set;
|
||||||
pub use crate::str::Str;
|
pub use crate::str::Str;
|
||||||
pub use crate::triple::Triple;
|
pub use crate::triple::Triple;
|
||||||
|
|
||||||
pub type RcArray<T> = std::rc::Rc<[T]>;
|
pub type ArcArray<T> = std::sync::Arc<[T]>;
|
||||||
|
|
||||||
pub fn open_read(filename: &str) -> std::io::Result<String> {
|
pub fn open_read(filename: &str) -> std::io::Result<String> {
|
||||||
let f = std::fs::File::open(filename)?;
|
let f = std::fs::File::open(filename)?;
|
||||||
|
|
|
@ -3,14 +3,14 @@ use std::fmt;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::ops::{Add, Deref};
|
use std::ops::{Add, Deref};
|
||||||
|
|
||||||
pub type RcStr = std::rc::Rc<str>;
|
pub type ArcStr = std::sync::Arc<str>;
|
||||||
|
|
||||||
/// Used to hold an immutable string.
|
/// Used to hold an immutable string.
|
||||||
///
|
///
|
||||||
/// It can construct as a const (by Str::ever).
|
/// It can construct as a const (by Str::ever).
|
||||||
#[derive(Debug, Clone, Eq)]
|
#[derive(Debug, Clone, Eq)]
|
||||||
pub enum Str {
|
pub enum Str {
|
||||||
Rc(RcStr),
|
Rc(ArcStr),
|
||||||
Static(&'static str),
|
Static(&'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,16 +93,16 @@ impl From<String> for Str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&RcStr> for Str {
|
impl From<&ArcStr> for Str {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(s: &RcStr) -> Self {
|
fn from(s: &ArcStr) -> Self {
|
||||||
Str::Rc(s.clone())
|
Str::Rc(s.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<RcStr> for Str {
|
impl From<ArcStr> for Str {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(s: RcStr) -> Self {
|
fn from(s: ArcStr) -> Self {
|
||||||
Str::Rc(s)
|
Str::Rc(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,10 +159,10 @@ impl Str {
|
||||||
Str::Rc(s.into())
|
Str::Rc(s.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_rc(self) -> RcStr {
|
pub fn into_rc(self) -> ArcStr {
|
||||||
match self {
|
match self {
|
||||||
Str::Rc(s) => s,
|
Str::Rc(s) => s,
|
||||||
Str::Static(s) => RcStr::from(s),
|
Str::Static(s) => ArcStr::from(s),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use erg_common::log;
|
||||||
use erg_common::set::Set;
|
use erg_common::set::Set;
|
||||||
use erg_common::traits::{Locational, Stream};
|
use erg_common::traits::{Locational, Stream};
|
||||||
use erg_common::{dict, fmt_vec, fn_name, option_enum_unwrap, set};
|
use erg_common::{dict, fmt_vec, fn_name, option_enum_unwrap, set};
|
||||||
use erg_common::{RcArray, Str};
|
use erg_common::{ArcArray, Str};
|
||||||
use OpKind::*;
|
use OpKind::*;
|
||||||
|
|
||||||
use erg_parser::ast::Dict as AstDict;
|
use erg_parser::ast::Dict as AstDict;
|
||||||
|
@ -374,7 +374,7 @@ impl Context {
|
||||||
let elem = self.eval_const_expr(&elem.expr)?;
|
let elem = self.eval_const_expr(&elem.expr)?;
|
||||||
elems.push(elem);
|
elems.push(elem);
|
||||||
}
|
}
|
||||||
Ok(ValueObj::Array(RcArray::from(elems)))
|
Ok(ValueObj::Array(ArcArray::from(elems)))
|
||||||
}
|
}
|
||||||
_ => Err(EvalErrors::from(EvalError::not_const_expr(
|
_ => Err(EvalErrors::from(EvalError::not_const_expr(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
|
@ -434,7 +434,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(ValueObj::Tuple(RcArray::from(elems)))
|
Ok(ValueObj::Tuple(ArcArray::from(elems)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_const_record(&self, record: &Record) -> EvalResult<ValueObj> {
|
fn eval_const_record(&self, record: &Record) -> EvalResult<ValueObj> {
|
||||||
|
|
|
@ -9,7 +9,7 @@ use erg_common::python_util::PythonVersion;
|
||||||
use erg_common::serialize::DataTypePrefix;
|
use erg_common::serialize::DataTypePrefix;
|
||||||
use erg_common::traits::ExitStatus;
|
use erg_common::traits::ExitStatus;
|
||||||
use erg_common::{fn_name, switch_lang};
|
use erg_common::{fn_name, switch_lang};
|
||||||
use erg_common::{RcArray, Str};
|
use erg_common::{ArcArray, Str};
|
||||||
|
|
||||||
use super::codeobj::CodeObj;
|
use super::codeobj::CodeObj;
|
||||||
use super::constructors::array_t;
|
use super::constructors::array_t;
|
||||||
|
@ -282,7 +282,7 @@ impl Deserializer {
|
||||||
&mut self,
|
&mut self,
|
||||||
v: &mut Vec<u8>,
|
v: &mut Vec<u8>,
|
||||||
python_ver: PythonVersion,
|
python_ver: PythonVersion,
|
||||||
) -> DeserializeResult<RcArray<ValueObj>> {
|
) -> DeserializeResult<ArcArray<ValueObj>> {
|
||||||
match self.deserialize_const(v, python_ver)? {
|
match self.deserialize_const(v, python_ver)? {
|
||||||
ValueObj::Array(arr) => Ok(arr),
|
ValueObj::Array(arr) => Ok(arr),
|
||||||
other => Err(DeserializeError::type_error(&Type::Str, other.ref_t())),
|
other => Err(DeserializeError::type_error(&Type::Str, other.ref_t())),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::{Add, Div, Mul, Neg, Range, RangeInclusive, Sub};
|
use std::ops::{Add, Div, Mul, Neg, Range, RangeInclusive, Sub};
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use erg_common::dict::Dict;
|
use erg_common::dict::Dict;
|
||||||
use erg_common::set;
|
use erg_common::set;
|
||||||
|
@ -522,14 +522,14 @@ impl TryFrom<TyParam> for ValueObj {
|
||||||
for tp in tps {
|
for tp in tps {
|
||||||
vals.push(ValueObj::try_from(tp)?);
|
vals.push(ValueObj::try_from(tp)?);
|
||||||
}
|
}
|
||||||
Ok(ValueObj::Array(Rc::from(vals)))
|
Ok(ValueObj::Array(Arc::from(vals)))
|
||||||
}
|
}
|
||||||
TyParam::Tuple(tps) => {
|
TyParam::Tuple(tps) => {
|
||||||
let mut vals = vec![];
|
let mut vals = vec![];
|
||||||
for tp in tps {
|
for tp in tps {
|
||||||
vals.push(ValueObj::try_from(tp)?);
|
vals.push(ValueObj::try_from(tp)?);
|
||||||
}
|
}
|
||||||
Ok(ValueObj::Tuple(Rc::from(vals)))
|
Ok(ValueObj::Tuple(Arc::from(vals)))
|
||||||
}
|
}
|
||||||
TyParam::Dict(tps) => {
|
TyParam::Dict(tps) => {
|
||||||
let mut vals = dict! {};
|
let mut vals = dict! {};
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::cmp::Ordering;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::ops::Neg;
|
use std::ops::Neg;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use erg_common::config::Input;
|
use erg_common::config::Input;
|
||||||
use erg_common::dict::Dict;
|
use erg_common::dict::Dict;
|
||||||
|
@ -15,7 +15,7 @@ use erg_common::python_util::PythonVersion;
|
||||||
use erg_common::serialize::*;
|
use erg_common::serialize::*;
|
||||||
use erg_common::set::Set;
|
use erg_common::set::Set;
|
||||||
use erg_common::{dict, fmt_iter, impl_display_from_debug, log, switch_lang};
|
use erg_common::{dict, fmt_iter, impl_display_from_debug, log, switch_lang};
|
||||||
use erg_common::{RcArray, Str};
|
use erg_common::{ArcArray, Str};
|
||||||
use erg_parser::ast::{ConstArgs, ConstExpr};
|
use erg_parser::ast::{ConstArgs, ConstExpr};
|
||||||
|
|
||||||
use crate::context::eval::type_from_token_kind;
|
use crate::context::eval::type_from_token_kind;
|
||||||
|
@ -436,10 +436,10 @@ pub enum ValueObj {
|
||||||
Float(f64),
|
Float(f64),
|
||||||
Str(Str),
|
Str(Str),
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Array(Rc<[ValueObj]>),
|
Array(ArcArray<ValueObj>),
|
||||||
Set(Set<ValueObj>),
|
Set(Set<ValueObj>),
|
||||||
Dict(Dict<ValueObj, ValueObj>),
|
Dict(Dict<ValueObj, ValueObj>),
|
||||||
Tuple(Rc<[ValueObj]>),
|
Tuple(ArcArray<ValueObj>),
|
||||||
Record(Dict<Field, ValueObj>),
|
Record(Dict<Field, ValueObj>),
|
||||||
DataClass {
|
DataClass {
|
||||||
name: Str,
|
name: Str,
|
||||||
|
@ -659,7 +659,7 @@ impl From<CodeObj> for ValueObj {
|
||||||
|
|
||||||
impl<V: Into<ValueObj>> From<Vec<V>> for ValueObj {
|
impl<V: Into<ValueObj>> From<Vec<V>> for ValueObj {
|
||||||
fn from(item: Vec<V>) -> Self {
|
fn from(item: Vec<V>) -> Self {
|
||||||
ValueObj::Array(RcArray::from(
|
ValueObj::Array(ArcArray::from(
|
||||||
&item.into_iter().map(Into::into).collect::<Vec<_>>()[..],
|
&item.into_iter().map(Into::into).collect::<Vec<_>>()[..],
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -667,7 +667,7 @@ impl<V: Into<ValueObj>> From<Vec<V>> for ValueObj {
|
||||||
|
|
||||||
impl<const N: usize, V: Into<ValueObj>> From<[V; N]> for ValueObj {
|
impl<const N: usize, V: Into<ValueObj>> From<[V; N]> for ValueObj {
|
||||||
fn from(item: [V; N]) -> Self {
|
fn from(item: [V; N]) -> Self {
|
||||||
ValueObj::Array(RcArray::from(&item.map(Into::into)[..]))
|
ValueObj::Array(ArcArray::from(&item.map(Into::into)[..]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,7 +912,7 @@ impl ValueObj {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tuple_from_const_args(args: ConstArgs) -> Self {
|
pub fn tuple_from_const_args(args: ConstArgs) -> Self {
|
||||||
Self::Tuple(Rc::from(&Self::vec_from_const_args(args)[..]))
|
Self::Tuple(Arc::from(&Self::vec_from_const_args(args)[..]))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vec_from_const_args(args: ConstArgs) -> Vec<Self> {
|
pub fn vec_from_const_args(args: ConstArgs) -> Vec<Self> {
|
||||||
|
@ -1012,7 +1012,7 @@ impl ValueObj {
|
||||||
(Self::Float(l), Self::Int(r)) => Some(Self::Float(l - r as f64)),
|
(Self::Float(l), Self::Int(r)) => Some(Self::Float(l - r as f64)),
|
||||||
(Self::Str(l), Self::Str(r)) => Some(Self::Str(Str::from(format!("{l}{r}")))),
|
(Self::Str(l), Self::Str(r)) => Some(Self::Str(Str::from(format!("{l}{r}")))),
|
||||||
(Self::Array(l), Self::Array(r)) => {
|
(Self::Array(l), Self::Array(r)) => {
|
||||||
let arr = Rc::from([l, r].concat());
|
let arr = Arc::from([l, r].concat());
|
||||||
Some(Self::Array(arr))
|
Some(Self::Array(arr))
|
||||||
}
|
}
|
||||||
(Self::Dict(l), Self::Dict(r)) => Some(Self::Dict(l.concat(r))),
|
(Self::Dict(l), Self::Dict(r)) => Some(Self::Dict(l.concat(r))),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue