mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-03 02:13:11 +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
|
||||
if self
|
||||
.file_cache
|
||||
.get(&uri)
|
||||
.unwrap()
|
||||
.get_line(pos.line)
|
||||
.get_line(&uri, pos.line)
|
||||
.map_or(false, |line| line.starts_with('#'))
|
||||
{
|
||||
return Ok(None);
|
||||
|
|
|
@ -65,7 +65,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
let dependents = self.dependents_of(&uri);
|
||||
for dep in dependents {
|
||||
// _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)?;
|
||||
}
|
||||
Ok(())
|
||||
|
@ -76,19 +76,19 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
let Some(ts) = self.file_cache.get_token_stream(&uri) else {
|
||||
return Ok(());
|
||||
};
|
||||
let mut parser = Parser::new(ts.clone());
|
||||
let mut parser = Parser::new(ts);
|
||||
if parser.parse().is_err() {
|
||||
return Ok(());
|
||||
}
|
||||
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") {
|
||||
"declare"
|
||||
} else {
|
||||
"exec"
|
||||
};
|
||||
let mut checker = self.get_checker(path);
|
||||
match checker.build(code.into(), mode) {
|
||||
match checker.build(code, mode) {
|
||||
Ok(artifact) => {
|
||||
self.artifacts.insert(uri.clone(), artifact.into());
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use lsp_types::{
|
|||
};
|
||||
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::shared::Shared;
|
||||
use erg_common::shared::AtomicShared;
|
||||
use erg_common::traits::DequeStream;
|
||||
use erg_compiler::erg_parser::lex::Lexer;
|
||||
use erg_compiler::erg_parser::token::{Token, TokenStream};
|
||||
|
@ -37,9 +37,9 @@ pub struct FileCacheEntry {
|
|||
|
||||
impl FileCacheEntry {
|
||||
/// 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();
|
||||
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.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FileCache {
|
||||
pub files: Shared<Dict<NormalizedUrl, FileCacheEntry>>,
|
||||
pub files: AtomicShared<Dict<NormalizedUrl, FileCacheEntry>>,
|
||||
}
|
||||
|
||||
impl FileCache {
|
||||
pub fn new() -> 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) {
|
||||
let workspace_folders = WorkspaceFoldersServerCapabilities {
|
||||
supported: Some(true),
|
||||
|
@ -98,36 +107,28 @@ impl FileCache {
|
|||
capabilities.text_document_sync = Some(TextDocumentSyncCapability::Options(sync_option));
|
||||
}
|
||||
|
||||
pub fn get_code(&self, uri: &NormalizedUrl) -> ELSResult<&str> {
|
||||
Ok(self.get(uri)?.code.as_str())
|
||||
/// This method clones and returns the entire file.
|
||||
/// 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> {
|
||||
let Some(entry) = unsafe { self.files.as_ref() }.get(uri) else {
|
||||
let code = _get_code_from_uri(uri)?;
|
||||
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_stream(&self, uri: &NormalizedUrl) -> Option<TokenStream> {
|
||||
let _ = self.load_once(uri);
|
||||
self.files.borrow_mut().get(uri)?.token_stream.clone()
|
||||
}
|
||||
|
||||
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() {
|
||||
if util::pos_in_loc(tok, pos) {
|
||||
return Some(tok.clone());
|
||||
|
@ -142,8 +143,17 @@ impl FileCache {
|
|||
pos: Position,
|
||||
offset: isize,
|
||||
) -> Option<Token> {
|
||||
let tokens = self.get_token_stream(uri)?;
|
||||
let index = self.get_token_index(uri, pos)?;
|
||||
let _ = self.load_once(uri);
|
||||
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;
|
||||
if index < tokens.len() {
|
||||
Some(tokens[index].clone())
|
||||
|
@ -153,8 +163,9 @@ impl FileCache {
|
|||
}
|
||||
|
||||
/// 0-based
|
||||
pub(crate) fn get_line(&self, uri: &NormalizedUrl, line: u32) -> Option<&str> {
|
||||
self.get(uri).ok().and_then(|ent| ent.get_line(line))
|
||||
pub(crate) fn get_line(&self, uri: &NormalizedUrl, line: u32) -> Option<String> {
|
||||
let _ = self.load_once(uri);
|
||||
self.files.borrow_mut().get(uri)?.get_line(line)
|
||||
}
|
||||
|
||||
pub(crate) fn get_ranged(
|
||||
|
@ -162,7 +173,9 @@ impl FileCache {
|
|||
uri: &NormalizedUrl,
|
||||
range: Range,
|
||||
) -> 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();
|
||||
for (i, line) in file.code.lines().enumerate() {
|
||||
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>) {
|
||||
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 ver.map_or(false, |ver| ver <= entry.ver) {
|
||||
// crate::_log!("171: double update detected: {ver:?}, {}, code:\n{}", entry.ver, entry.code);
|
||||
|
@ -206,6 +220,7 @@ impl FileCache {
|
|||
1
|
||||
}
|
||||
});
|
||||
drop(ent);
|
||||
self.files.borrow_mut().insert(
|
||||
uri.clone(),
|
||||
FileCacheEntry {
|
||||
|
@ -217,7 +232,8 @@ impl FileCache {
|
|||
}
|
||||
|
||||
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;
|
||||
};
|
||||
let mut code = entry.code.clone();
|
||||
|
@ -232,7 +248,8 @@ impl FileCache {
|
|||
|
||||
pub(crate) fn incremental_update(&self, params: DidChangeTextDocumentParams) {
|
||||
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;
|
||||
};
|
||||
if entry.ver >= params.text_document.version {
|
||||
|
|
|
@ -230,7 +230,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
};
|
||||
let mut prev_token = Token::DUMMY;
|
||||
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);
|
||||
};
|
||||
if token.deep_eq(&prev_token) {
|
||||
|
|
|
@ -91,7 +91,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
}
|
||||
// recheck dependencies and finally the file itself
|
||||
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)?;
|
||||
}
|
||||
// dependents are checked after changes are committed
|
||||
|
|
|
@ -290,9 +290,9 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
send_log(format!("full semantic tokens request: {params:?}"))?;
|
||||
let uri = NormalizedUrl::new(params.text_document.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 result = match builder.build_without_desugaring(src.to_string()) {
|
||||
let result = match builder.build_without_desugaring(src) {
|
||||
Ok(ast) => {
|
||||
let mut state = ASTSemanticState::new();
|
||||
let tokens = state.enumerate_tokens(ast);
|
||||
|
|
|
@ -507,7 +507,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
let uri =
|
||||
NormalizedUrl::parse(msg["params"]["textDocument"]["uri"].as_str().unwrap())?;
|
||||
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.check_file(uri, code)
|
||||
}
|
||||
|
|
|
@ -86,11 +86,9 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
args_loc: erg_common::error::Location,
|
||||
token: &Token,
|
||||
) -> usize {
|
||||
let tks = self.file_cache.get_token_stream(uri).unwrap();
|
||||
// we should use the latest commas
|
||||
let commas = self
|
||||
.file_cache
|
||||
.get_token_stream(uri)
|
||||
.unwrap()
|
||||
let commas = tks
|
||||
.iter()
|
||||
.skip_while(|&tk| tk.loc() < args_loc)
|
||||
.filter(|tk| tk.is(TokenKind::Comma) && args_loc.ln_end() >= tk.ln_begin())
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
use std::borrow::{Borrow, ToOwned};
|
||||
use std::cell::RefCell;
|
||||
use std::hash::Hash;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::thread::LocalKey;
|
||||
|
||||
use crate::dict::Dict;
|
||||
use crate::set::Set;
|
||||
use crate::{RcArray, Str};
|
||||
use crate::{ArcArray, Str};
|
||||
|
||||
#[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> {
|
||||
fn default() -> Self {
|
||||
|
@ -47,31 +47,31 @@ impl CacheSet<str> {
|
|||
}
|
||||
|
||||
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) {
|
||||
return cached.clone();
|
||||
} // &self.0 is dropped
|
||||
let s = RcArray::from(q);
|
||||
let s = ArcArray::from(q);
|
||||
self.0.borrow_mut().insert(s.clone());
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
Rc<T>: Borrow<Q>,
|
||||
Arc<T>: Borrow<Q>,
|
||||
Q: ToOwned<Owned = T>,
|
||||
{
|
||||
if let Some(cached) = self.0.borrow().get(q) {
|
||||
return cached.clone();
|
||||
} // &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());
|
||||
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>>>);
|
||||
|
|
|
@ -39,7 +39,7 @@ use crate::set::Set;
|
|||
pub use crate::str::Str;
|
||||
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> {
|
||||
let f = std::fs::File::open(filename)?;
|
||||
|
|
|
@ -3,14 +3,14 @@ use std::fmt;
|
|||
use std::hash::{Hash, Hasher};
|
||||
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.
|
||||
///
|
||||
/// It can construct as a const (by Str::ever).
|
||||
#[derive(Debug, Clone, Eq)]
|
||||
pub enum Str {
|
||||
Rc(RcStr),
|
||||
Rc(ArcStr),
|
||||
Static(&'static str),
|
||||
}
|
||||
|
||||
|
@ -93,16 +93,16 @@ impl From<String> for Str {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<&RcStr> for Str {
|
||||
impl From<&ArcStr> for Str {
|
||||
#[inline]
|
||||
fn from(s: &RcStr) -> Self {
|
||||
fn from(s: &ArcStr) -> Self {
|
||||
Str::Rc(s.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RcStr> for Str {
|
||||
impl From<ArcStr> for Str {
|
||||
#[inline]
|
||||
fn from(s: RcStr) -> Self {
|
||||
fn from(s: ArcStr) -> Self {
|
||||
Str::Rc(s)
|
||||
}
|
||||
}
|
||||
|
@ -159,10 +159,10 @@ impl Str {
|
|||
Str::Rc(s.into())
|
||||
}
|
||||
|
||||
pub fn into_rc(self) -> RcStr {
|
||||
pub fn into_rc(self) -> ArcStr {
|
||||
match self {
|
||||
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::traits::{Locational, Stream};
|
||||
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 erg_parser::ast::Dict as AstDict;
|
||||
|
@ -374,7 +374,7 @@ impl Context {
|
|||
let elem = self.eval_const_expr(&elem.expr)?;
|
||||
elems.push(elem);
|
||||
}
|
||||
Ok(ValueObj::Array(RcArray::from(elems)))
|
||||
Ok(ValueObj::Array(ArcArray::from(elems)))
|
||||
}
|
||||
_ => Err(EvalErrors::from(EvalError::not_const_expr(
|
||||
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> {
|
||||
|
|
|
@ -9,7 +9,7 @@ use erg_common::python_util::PythonVersion;
|
|||
use erg_common::serialize::DataTypePrefix;
|
||||
use erg_common::traits::ExitStatus;
|
||||
use erg_common::{fn_name, switch_lang};
|
||||
use erg_common::{RcArray, Str};
|
||||
use erg_common::{ArcArray, Str};
|
||||
|
||||
use super::codeobj::CodeObj;
|
||||
use super::constructors::array_t;
|
||||
|
@ -282,7 +282,7 @@ impl Deserializer {
|
|||
&mut self,
|
||||
v: &mut Vec<u8>,
|
||||
python_ver: PythonVersion,
|
||||
) -> DeserializeResult<RcArray<ValueObj>> {
|
||||
) -> DeserializeResult<ArcArray<ValueObj>> {
|
||||
match self.deserialize_const(v, python_ver)? {
|
||||
ValueObj::Array(arr) => Ok(arr),
|
||||
other => Err(DeserializeError::type_error(&Type::Str, other.ref_t())),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
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::set;
|
||||
|
@ -522,14 +522,14 @@ impl TryFrom<TyParam> for ValueObj {
|
|||
for tp in tps {
|
||||
vals.push(ValueObj::try_from(tp)?);
|
||||
}
|
||||
Ok(ValueObj::Array(Rc::from(vals)))
|
||||
Ok(ValueObj::Array(Arc::from(vals)))
|
||||
}
|
||||
TyParam::Tuple(tps) => {
|
||||
let mut vals = vec![];
|
||||
for tp in tps {
|
||||
vals.push(ValueObj::try_from(tp)?);
|
||||
}
|
||||
Ok(ValueObj::Tuple(Rc::from(vals)))
|
||||
Ok(ValueObj::Tuple(Arc::from(vals)))
|
||||
}
|
||||
TyParam::Dict(tps) => {
|
||||
let mut vals = dict! {};
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::cmp::Ordering;
|
|||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::Neg;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use erg_common::config::Input;
|
||||
use erg_common::dict::Dict;
|
||||
|
@ -15,7 +15,7 @@ use erg_common::python_util::PythonVersion;
|
|||
use erg_common::serialize::*;
|
||||
use erg_common::set::Set;
|
||||
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 crate::context::eval::type_from_token_kind;
|
||||
|
@ -436,10 +436,10 @@ pub enum ValueObj {
|
|||
Float(f64),
|
||||
Str(Str),
|
||||
Bool(bool),
|
||||
Array(Rc<[ValueObj]>),
|
||||
Array(ArcArray<ValueObj>),
|
||||
Set(Set<ValueObj>),
|
||||
Dict(Dict<ValueObj, ValueObj>),
|
||||
Tuple(Rc<[ValueObj]>),
|
||||
Tuple(ArcArray<ValueObj>),
|
||||
Record(Dict<Field, ValueObj>),
|
||||
DataClass {
|
||||
name: Str,
|
||||
|
@ -659,7 +659,7 @@ impl From<CodeObj> for ValueObj {
|
|||
|
||||
impl<V: Into<ValueObj>> From<Vec<V>> for ValueObj {
|
||||
fn from(item: Vec<V>) -> Self {
|
||||
ValueObj::Array(RcArray::from(
|
||||
ValueObj::Array(ArcArray::from(
|
||||
&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 {
|
||||
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 {
|
||||
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> {
|
||||
|
@ -1012,7 +1012,7 @@ impl ValueObj {
|
|||
(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::Array(l), Self::Array(r)) => {
|
||||
let arr = Rc::from([l, r].concat());
|
||||
let arr = Arc::from([l, r].concat());
|
||||
Some(Self::Array(arr))
|
||||
}
|
||||
(Self::Dict(l), Self::Dict(r)) => Some(Self::Dict(l.concat(r))),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue