feat: reference destructuring pattern { a: a } := &o

This commit is contained in:
Mark
2025-11-14 21:14:43 +01:00
parent 9e4eece87c
commit 6914b1dba2
22 changed files with 271 additions and 119 deletions

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "mers" name = "mers"
version = "0.9.26" version = "0.9.28"
edition = "2021" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "dynamically typed but type-checked programming language" description = "dynamically typed but type-checked programming language"
@@ -15,7 +15,7 @@ default = ["colored-output"]
colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"] colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"]
[dependencies] [dependencies]
mers_lib = "0.9.26" mers_lib = "0.9.28"
# mers_lib = { path = "../mers_lib" } # mers_lib = { path = "../mers_lib" }
clap = { version = "4.3.19", features = ["derive"] } clap = { version = "4.3.19", features = ["derive"] }
colored = { version = "2.1.0", optional = true } colored = { version = "2.1.0", optional = true }

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "mers_lib" name = "mers_lib"
version = "0.9.26" version = "0.9.28"
edition = "2021" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
description = "library to use the mers language in other projects" description = "library to use the mers language in other projects"

View File

@@ -6,33 +6,70 @@ pub fn assign(from: &Data, target: &Data) {
.as_any() .as_any()
.downcast_ref::<crate::data::reference::Reference>() .downcast_ref::<crate::data::reference::Reference>()
{ {
*r.0.write().unwrap() = from.clone(); *r.write() = from.clone();
} else if let (Some(from), Some(target)) = ( } else if let (Some((from, from_ref)), Some(target)) = (
from.get() from.get()
.as_any() .as_any()
.downcast_ref::<crate::data::tuple::Tuple>(), .downcast_ref::<crate::data::tuple::Tuple>()
.map(|v| (v.clone(), false))
.or_else(|| {
from.get()
.as_any()
.downcast_ref::<crate::data::reference::Reference>()
.and_then(|r| {
r.read()
.get()
.as_any()
.downcast_ref::<crate::data::tuple::Tuple>()
.map(|v| (v.clone_refs(), true))
})
}),
target target
.get() .get()
.as_any() .as_any()
.downcast_ref::<crate::data::tuple::Tuple>(), .downcast_ref::<crate::data::tuple::Tuple>(),
) { ) {
for (from, target) in from.0.iter().zip(target.0.iter()) { for (from, target) in from.0.into_iter().zip(target.0.iter()) {
assign(from, target); if from_ref {
assign(&Data::new(from), &*target.read());
} else {
assign(&*from.read(), &*target.read());
} }
} else if let (Some(from), Some(target)) = ( }
} else if let (Some((from, from_ref)), Some(target)) = (
from.get() from.get()
.as_any() .as_any()
.downcast_ref::<crate::data::object::Object>(), .downcast_ref::<crate::data::object::Object>()
.map(|v| (v.clone(), false))
.or_else(|| {
from.get()
.as_any()
.downcast_ref::<crate::data::reference::Reference>()
.and_then(|r| {
r.read()
.get()
.as_any()
.downcast_ref::<crate::data::object::Object>()
.map(|v| (v.clone_refs(), true))
})
}),
target target
.get() .get()
.as_any() .as_any()
.downcast_ref::<crate::data::object::Object>(), .downcast_ref::<crate::data::object::Object>(),
) { ) {
for (field, target) in target.iter() { for (field, target) in target.iter() {
if from_ref {
let from = from
.get_mut(*field)
.expect("type-checks should guarantee that from has every field of target");
assign(&Data::new(from.clone_ref()), &*target.read());
} else {
let from = from let from = from
.get(*field) .get(*field)
.expect("type-checks should guarantee that from has every field of target"); .expect("type-checks should guarantee that from has every field of target");
assign(from, target); assign(&from, &*target.read());
}
} }
} else { } else {
unreachable!("invalid assignment") unreachable!("invalid assignment")

View File

@@ -225,7 +225,7 @@ impl Data {
Self::new(tuple::Tuple(vec![])) Self::new(tuple::Tuple(vec![]))
} }
pub fn one_tuple(v: Self) -> Self { pub fn one_tuple(v: Self) -> Self {
Self::new(tuple::Tuple(vec![v])) Self::new(tuple::Tuple::from([v]))
} }
/// Returns true if self is `()`. /// Returns true if self is `()`.
pub fn is_zero_tuple(&self) -> bool { pub fn is_zero_tuple(&self) -> bool {
@@ -253,13 +253,13 @@ impl Data {
None None
} }
} }
pub fn get(&self) -> RwLockReadGuard<Box<dyn MersData>> { pub fn get(&'_ self) -> RwLockReadGuard<'_, Box<dyn MersData>> {
self.data.read().unwrap() self.data.read().unwrap()
} }
pub fn get_mut_unchecked(&self) -> RwLockWriteGuard<Box<dyn MersData>> { pub fn get_mut_unchecked(&'_ self) -> RwLockWriteGuard<'_, Box<dyn MersData>> {
self.data.write().unwrap() self.data.write().unwrap()
} }
pub fn try_get_mut(&self) -> Option<RwLockWriteGuard<Box<dyn MersData>>> { pub fn try_get_mut(&'_ self) -> Option<RwLockWriteGuard<'_, Box<dyn MersData>>> {
if self.is_mut && self.counts.0.load(std::sync::atomic::Ordering::Relaxed) == 0 { if self.is_mut && self.counts.0.load(std::sync::atomic::Ordering::Relaxed) == 0 {
Some(self.get_mut_unchecked()) Some(self.get_mut_unchecked())
} else { } else {
@@ -268,7 +268,7 @@ impl Data {
} }
/// like try_get_mut, but instead of returning `None` this function `get()`s the data and clones it. /// like try_get_mut, but instead of returning `None` this function `get()`s the data and clones it.
/// When cloning data, this transforms `self` into a `Data` with `is_mut: true`, hence the `&mut self` parameter. /// When cloning data, this transforms `self` into a `Data` with `is_mut: true`, hence the `&mut self` parameter.
pub fn get_mut(&mut self) -> RwLockWriteGuard<Box<dyn MersData>> { pub fn get_mut(&'_ mut self) -> RwLockWriteGuard<'_, Box<dyn MersData>> {
if self.try_get_mut().is_none() { if self.try_get_mut().is_none() {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
eprintln!( eprintln!(

View File

@@ -7,18 +7,33 @@ use crate::info::DisplayInfo;
use super::{Data, MersData, MersDataWInfo, MersType, Type}; use super::{Data, MersData, MersDataWInfo, MersType, Type};
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq)]
pub struct Object(Vec<(usize, Data)>); pub struct Object(Vec<(usize, super::reference::Reference)>);
impl Object { impl Object {
pub fn new(v: Vec<(usize, Data)>) -> Self { pub fn new(v: impl IntoIterator<Item = (usize, Data)>) -> Self {
Self(v) Self(
v.into_iter()
.map(|(i, d)| (i, super::reference::Reference::from(d)))
.collect(),
)
} }
pub fn get(&self, f: usize) -> Option<&Data> { pub fn get(&self, f: usize) -> Option<Data> {
self.iter().find(|v| v.0 == f).map(|v| &v.1) self.iter().find(|v| v.0 == f).map(|v| v.1.read().clone())
} }
pub fn iter(&self) -> std::slice::Iter<(usize, Data)> { pub fn get_mut(&self, f: usize) -> Option<&super::reference::Reference> {
self.iter().find(|v| v.0 == f).map(|(_, v)| v)
}
pub fn iter(&'_ self) -> std::slice::Iter<'_, (usize, super::reference::Reference)> {
self.0.iter() self.0.iter()
} }
pub fn clone_refs(&self) -> Self {
Self(self.0.iter().map(|(i, r)| (*i, r.clone_ref())).collect())
}
}
impl Clone for Object {
fn clone(&self) -> Self {
Self(self.0.iter().map(|(i, r)| (*i, r.clone_data())).collect())
}
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ObjectT(Vec<(usize, Type)>); pub struct ObjectT(Vec<(usize, Type)>);
@@ -29,7 +44,7 @@ impl ObjectT {
pub fn get(&self, f: usize) -> Option<&Type> { pub fn get(&self, f: usize) -> Option<&Type> {
self.iter().find(|v| v.0 == f).map(|v| &v.1) self.iter().find(|v| v.0 == f).map(|v| &v.1)
} }
pub fn iter(&self) -> std::slice::Iter<(usize, Type)> { pub fn iter(&'_ self) -> std::slice::Iter<'_, (usize, Type)> {
self.0.iter() self.0.iter()
} }
fn len(&self) -> usize { fn len(&self) -> usize {
@@ -49,7 +64,7 @@ impl MersData for Object {
f, f,
"{}: {}", "{}: {}",
info.get_object_field_name(*field), info.get_object_field_name(*field),
val.get().with_display(info) val.read().get().with_display(info)
)?; )?;
comma_sep = true; comma_sep = true;
} }
@@ -69,7 +84,7 @@ impl MersData for Object {
fn as_type(&self) -> Type { fn as_type(&self) -> Type {
Type::new(ObjectT( Type::new(ObjectT(
self.iter() self.iter()
.map(|(n, v)| (n.clone(), v.get().as_type())) .map(|(n, v)| (n.clone(), v.read().get().as_type()))
.collect(), .collect(),
)) ))
} }

View File

@@ -1,14 +1,32 @@
use std::{ use std::{
any::Any, any::Any,
sync::{Arc, RwLock}, sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
}; };
use crate::{errors::CheckError, info::DisplayInfo}; use crate::{errors::CheckError, info::DisplayInfo};
use super::{Data, MersData, MersType, Type}; use super::{Data, MersData, MersType, Type};
#[derive(Debug, Clone)] #[derive(Debug)]
pub struct Reference(pub Arc<RwLock<Data>>); pub struct Reference(Arc<RwLock<Data>>);
impl Reference {
/// Creates a reference from data,
/// so that the original data can't be
/// modified through the new reference.
pub fn from(data: Data) -> Self {
Self(Arc::new(RwLock::new(data.mkref().0)))
}
pub fn raw(reference: Arc<RwLock<Data>>) -> Self {
Self(reference)
}
pub fn read(&'_ self) -> RwLockReadGuard<'_, Data> {
self.0.read().unwrap()
}
pub fn write(&'_ self) -> RwLockWriteGuard<'_, Data> {
self.0.write().unwrap()
}
}
impl MersData for Reference { impl MersData for Reference {
fn display(&self, info: &DisplayInfo<'_>, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn display(&self, info: &DisplayInfo<'_>, f: &mut std::fmt::Formatter) -> std::fmt::Result {
@@ -79,7 +97,7 @@ impl MersData for Reference {
} }
} }
fn clone(&self) -> Box<dyn MersData> { fn clone(&self) -> Box<dyn MersData> {
Box::new(Clone::clone(self)) Box::new(self.clone_ref())
} }
fn as_type(&self) -> Type { fn as_type(&self) -> Type {
Type::new(ReferenceT(self.0.read().unwrap().get().as_type())) Type::new(ReferenceT(self.0.read().unwrap().get().as_type()))
@@ -95,6 +113,23 @@ impl MersData for Reference {
} }
} }
impl Reference {
pub fn clone_ref(&self) -> Self {
Self(Arc::clone(&self.0))
}
pub fn clone_data(&self) -> Self {
Self(Arc::new(RwLock::new(
self.0.read().unwrap().clone().mkref().0,
)))
}
}
impl PartialEq for Reference {
fn eq(&self, other: &Self) -> bool {
*self.0.read().unwrap() == *other.0.read().unwrap()
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ReferenceT(pub Type); pub struct ReferenceT(pub Type);
impl MersType for ReferenceT { impl MersType for ReferenceT {

View File

@@ -4,15 +4,38 @@ use crate::{errors::CheckError, info::DisplayInfo};
use super::{Data, MersData, MersType, Type}; use super::{Data, MersData, MersType, Type};
#[derive(Debug, Clone)] #[derive(Debug)]
pub struct Tuple(pub Vec<Data>); pub struct Tuple(pub Vec<super::reference::Reference>);
impl Tuple { impl Tuple {
pub fn empty() -> Self {
Self(vec![])
}
pub fn from(elems: impl IntoIterator<Item = Data>) -> Self {
Self(
elems
.into_iter()
.map(|d| super::reference::Reference::from(d))
.collect(),
)
}
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.0.len() self.0.len()
} }
pub fn get(&self, i: usize) -> Option<&Data> { pub fn get(&self, i: usize) -> Option<Data> {
self.0.get(i) self.0.get(i).map(|v| v.read().clone())
}
pub fn get_mut(&self, i: usize) -> Option<super::reference::Reference> {
self.0.get(i).map(|v| v.clone_ref())
}
pub fn clone_refs(&self) -> Self {
Self(self.0.iter().map(|r| r.clone_ref()).collect())
}
}
impl Clone for Tuple {
fn clone(&self) -> Self {
Self(self.0.iter().map(|r| r.clone_data()).collect())
} }
} }
@@ -23,7 +46,7 @@ impl MersData for Tuple {
if i > 0 { if i > 0 {
write!(f, ", ")?; write!(f, ", ")?;
} }
c.get().display(info, f)?; c.read().get().display(info, f)?;
} }
write!(f, ")")?; write!(f, ")")?;
Ok(()) Ok(())
@@ -39,13 +62,21 @@ impl MersData for Tuple {
&self, &self,
_gi: &crate::program::run::RunLocalGlobalInfo, _gi: &crate::program::run::RunLocalGlobalInfo,
) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> { ) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
Some(Box::new(self.0.clone().into_iter().map(Ok))) Some(Box::new(
Clone::clone(self)
.0
.into_iter()
.map(|r| r.read().clone())
.map(Ok),
))
} }
fn clone(&self) -> Box<dyn MersData> { fn clone(&self) -> Box<dyn MersData> {
Box::new(Clone::clone(self)) Box::new(Clone::clone(self))
} }
fn as_type(&self) -> Type { fn as_type(&self) -> Type {
Type::new(TupleT(self.0.iter().map(|v| v.get().as_type()).collect())) Type::new(TupleT(
self.0.iter().map(|v| v.read().get().as_type()).collect(),
))
} }
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self

View File

@@ -178,7 +178,7 @@ impl CheckErrorHRConfig {
.color(s, EColor::Indent(self.color_index), &mut t); .color(s, EColor::Indent(self.color_index), &mut t);
return t; return t;
} }
pub fn indent_start(&self, right: bool) -> IndentStr { pub fn indent_start(&'_ self, right: bool) -> IndentStr<'_> {
IndentStr( IndentStr(
&self.idt_start, &self.idt_start,
self.color( self.color(
@@ -186,13 +186,13 @@ impl CheckErrorHRConfig {
), ),
) )
} }
pub fn indent_default(&self, right: bool) -> IndentStr { pub fn indent_default(&'_ self, right: bool) -> IndentStr<'_> {
IndentStr( IndentStr(
&self.idt_default, &self.idt_default,
self.color(Self::CHARS[self.style as usize][1][right as usize]), self.color(Self::CHARS[self.style as usize][1][right as usize]),
) )
} }
pub fn indent_end(&self, right: bool) -> IndentStr { pub fn indent_end(&'_ self, right: bool) -> IndentStr<'_> {
IndentStr( IndentStr(
&self.idt_end, &self.idt_end,
self.color( self.color(
@@ -200,7 +200,7 @@ impl CheckErrorHRConfig {
), ),
) )
} }
pub fn indent_single(&self, right: bool) -> IndentStr { pub fn indent_single(&'_ self, right: bool) -> IndentStr<'_> {
IndentStr( IndentStr(
&self.idt_single, &self.idt_single,
self.color(if self.is_inner { self.color(if self.is_inner {

View File

@@ -43,7 +43,7 @@ impl<A: FromMersData> FromMersData for OneOrNone<A> {
if v.0.is_empty() { if v.0.is_empty() {
f(Some(Self(None))) f(Some(Self(None)))
} else { } else {
A::try_represent(v.0[0].get().as_ref(), |v1| { A::try_represent(v.0[0].read().get().as_ref(), |v1| {
if let Some(va) = v1 { if let Some(va) = v1 {
f(Some(Self(Some(va)))) f(Some(Self(Some(va))))
} else { } else {
@@ -205,7 +205,7 @@ impl<A: FromMersData> FromMersData for (A,) {
.downcast_ref::<data::tuple::Tuple>() .downcast_ref::<data::tuple::Tuple>()
.filter(|v| v.0.len() == 1) .filter(|v| v.0.len() == 1)
{ {
A::try_represent(v.0[0].get().as_ref(), |v1| { A::try_represent(v.0[0].read().get().as_ref(), |v1| {
if let Some(va) = v1 { if let Some(va) = v1 {
f(Some((va,))) f(Some((va,)))
} else { } else {
@@ -222,7 +222,7 @@ impl<A: ToMersData> ToMersData for (A,) {
Type::new(data::tuple::TupleT(vec![A::as_type_to()])) Type::new(data::tuple::TupleT(vec![A::as_type_to()]))
} }
fn represent(self) -> Data { fn represent(self) -> Data {
Data::new(data::tuple::Tuple(vec![self.0.represent()])) Data::new(data::tuple::Tuple::from([self.0.represent()]))
} }
} }
@@ -242,9 +242,9 @@ impl<A: FromMersData, B: FromMersData> FromMersData for (A, B) {
.downcast_ref::<data::tuple::Tuple>() .downcast_ref::<data::tuple::Tuple>()
.filter(|v| v.0.len() == 2) .filter(|v| v.0.len() == 2)
{ {
A::try_represent(v.0[0].get().as_ref(), |v1| { A::try_represent(v.0[0].read().get().as_ref(), |v1| {
if let Some(va) = v1 { if let Some(va) = v1 {
B::try_represent(v.0[1].get().as_ref(), |v2| { B::try_represent(v.0[1].read().get().as_ref(), |v2| {
if let Some(vb) = v2 { if let Some(vb) = v2 {
f(Some((va, vb))) f(Some((va, vb)))
} else { } else {
@@ -265,7 +265,7 @@ impl<A: ToMersData, B: ToMersData> ToMersData for (A, B) {
Type::new(data::tuple::TupleT(vec![A::as_type_to(), B::as_type_to()])) Type::new(data::tuple::TupleT(vec![A::as_type_to(), B::as_type_to()]))
} }
fn represent(self) -> Data { fn represent(self) -> Data {
Data::new(data::tuple::Tuple(vec![ Data::new(data::tuple::Tuple::from([
self.0.represent(), self.0.represent(),
self.1.represent(), self.1.represent(),
])) ]))
@@ -288,11 +288,11 @@ impl<A: FromMersData, B: FromMersData, C: FromMersData> FromMersData for (A, B,
.downcast_ref::<data::tuple::Tuple>() .downcast_ref::<data::tuple::Tuple>()
.filter(|v| v.0.len() == 3) .filter(|v| v.0.len() == 3)
{ {
A::try_represent(v.0[0].get().as_ref(), |v1| { A::try_represent(v.0[0].read().get().as_ref(), |v1| {
if let Some(va) = v1 { if let Some(va) = v1 {
B::try_represent(v.0[1].get().as_ref(), |v2| { B::try_represent(v.0[1].read().get().as_ref(), |v2| {
if let Some(vb) = v2 { if let Some(vb) = v2 {
C::try_represent(v.0[2].get().as_ref(), |v3| { C::try_represent(v.0[2].read().get().as_ref(), |v3| {
if let Some(vc) = v3 { if let Some(vc) = v3 {
f(Some((va, vb, vc))) f(Some((va, vb, vc)))
} else { } else {
@@ -321,7 +321,7 @@ impl<A: ToMersData, B: ToMersData, C: ToMersData> ToMersData for (A, B, C) {
])) ]))
} }
fn represent(self) -> Data { fn represent(self) -> Data {
Data::new(data::tuple::Tuple(vec![ Data::new(data::tuple::Tuple::from([
self.0.represent(), self.0.represent(),
self.1.represent(), self.1.represent(),
self.2.represent(), self.2.represent(),

View File

@@ -100,8 +100,10 @@ pub fn to_mers_func_concrete_string_string_to_any(
move |a, _| { move |a, _| {
let a = a.get(); let a = a.get();
let a = &a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap().0; let a = &a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap().0;
let l = a[0].get(); let l = a[0].read();
let r = a[1].get(); let l = l.get();
let r = a[1].read();
let r = r.get();
f( f(
l.as_any() l.as_any()
.downcast_ref::<data::string::String>() .downcast_ref::<data::string::String>()

View File

@@ -1,5 +1,5 @@
use std::{ use std::{
sync::{Arc, Mutex, RwLock}, sync::{Arc, Mutex},
time::{Duration, Instant}, time::{Duration, Instant},
}; };
@@ -68,10 +68,12 @@ impl Config {
run: Arc::new(|a, i| { run: Arc::new(|a, i| {
let a = a.get(); let a = a.get();
let a = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let a = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
let arg_ref = a.0[0].get(); let arg_ref = a.0[0].read();
let arg_ref = arg_ref.get();
let arg_ref = arg_ref.as_any().downcast_ref::<data::reference::Reference>().unwrap(); let arg_ref = arg_ref.as_any().downcast_ref::<data::reference::Reference>().unwrap();
let mut arg = arg_ref.0.write().unwrap(); let mut arg = arg_ref.write();
let func = a.0[1].get(); let func = a.0[1].read();
let func = func.get();
*arg = func.execute(arg.clone(), &i.global).unwrap()?; *arg = func.execute(arg.clone(), &i.global).unwrap()?;
Ok(Data::empty_tuple()) Ok(Data::empty_tuple())
}), }),
@@ -168,7 +170,7 @@ impl Config {
fixed_type_out: Arc::new(Mutex::new(None)), fixed_type_out: Arc::new(Mutex::new(None)),
out: Ok(Arc::new(|a, _i| Ok(Type::new(data::reference::ReferenceT(a.clone()))))), out: Ok(Arc::new(|a, _i| Ok(Type::new(data::reference::ReferenceT(a.clone()))))),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
Ok(Data::new(data::reference::Reference(Arc::new(RwLock::new(a.clone()))))) Ok(Data::new(data::reference::Reference::from(a)))
}), }),
inner_statements: None, inner_statements: None,
}, },
@@ -188,7 +190,7 @@ impl Config {
.as_any() .as_any()
.downcast_ref::<data::reference::Reference>() .downcast_ref::<data::reference::Reference>()
{ {
Ok(r.0.write().unwrap().clone()) Ok(r.read().clone())
} else { } else {
Err("called deref on non-reference".into()) Err("called deref on non-reference".into())
} }

View File

@@ -53,7 +53,7 @@ impl Config {
run: Arc::new(|a, i| { run: Arc::new(|a, i| {
let a = a.get(); let a = a.get();
let cmd = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let cmd = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
let (cmd, args) = (&cmd.0[0], &cmd.0[1]); let (cmd, args) = (&cmd.0[0].read(), &cmd.0[1].read());
let cmd = cmd.get(); let cmd = cmd.get();
let (cmd, args) = ( let (cmd, args) = (
cmd.as_any().downcast_ref::<data::string::String>().unwrap(), cmd.as_any().downcast_ref::<data::string::String>().unwrap(),
@@ -74,7 +74,7 @@ impl Config {
String::from_utf8_lossy(&output.stdout).into_owned(); String::from_utf8_lossy(&output.stdout).into_owned();
let stderr = let stderr =
String::from_utf8_lossy(&output.stderr).into_owned(); String::from_utf8_lossy(&output.stderr).into_owned();
Ok(Data::new(data::tuple::Tuple(vec![ Ok(Data::new(data::tuple::Tuple::from([
status, status,
Data::new(data::string::String(stdout)), Data::new(data::string::String(stdout)),
Data::new(data::string::String(stderr)), Data::new(data::string::String(stderr)),
@@ -106,7 +106,7 @@ impl Config {
run: Arc::new(|a, i| { run: Arc::new(|a, i| {
let a = a.get(); let a = a.get();
let cmd = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let cmd = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
let (cmd, args) = (&cmd.0[0], &cmd.0[1]); let (cmd, args) = (&cmd.0[0].read(), &cmd.0[1].read());
let cmd = cmd.get(); let cmd = cmd.get();
let (cmd, args) = ( let (cmd, args) = (
cmd.as_any().downcast_ref::<data::string::String>().unwrap(), cmd.as_any().downcast_ref::<data::string::String>().unwrap(),
@@ -215,8 +215,10 @@ impl Config {
run: Arc::new(|a, i| { run: Arc::new(|a, i| {
let a = a.get(); let a = a.get();
let tuple = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let tuple = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
let child = tuple.0[0].get(); let child = tuple.0[0].read();
let bytes = tuple.0[1].get(); let child = child.get();
let bytes = tuple.0[1].read();
let bytes = bytes.get();
let child = child.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = child.as_any().downcast_ref::<ChildProcess>().unwrap();
let mut child = child.0.lock().unwrap(); let mut child = child.0.lock().unwrap();
let buf = bytes.iterable(&i.global).unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::byte::Byte>().unwrap().0)).collect::<Result<Vec<_>, _>>()?; let buf = bytes.iterable(&i.global).unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::byte::Byte>().unwrap().0)).collect::<Result<Vec<_>, _>>()?;
@@ -246,8 +248,10 @@ impl Config {
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let a = a.get(); let a = a.get();
let tuple = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let tuple = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
let child = tuple.0[0].get(); let child = tuple.0[0].read();
let string = tuple.0[1].get(); let child = child.get();
let string = tuple.0[1].read();
let string = string.get();
let child = child.as_any().downcast_ref::<ChildProcess>().unwrap(); let child = child.as_any().downcast_ref::<ChildProcess>().unwrap();
let mut child = child.0.lock().unwrap(); let mut child = child.0.lock().unwrap();
let buf = string.as_any().downcast_ref::<data::string::String>().unwrap().0.as_bytes(); let buf = string.as_any().downcast_ref::<data::string::String>().unwrap().0.as_bytes();

View File

@@ -76,7 +76,8 @@ impl Config {
.as_any() .as_any()
.downcast_ref::<Tuple>() .downcast_ref::<Tuple>()
.expect("got non-tuple argument to fs_read_text"); .expect("got non-tuple argument to fs_read_text");
let (a, b) = (a.0[0].get(), a.0[1].get()); let (a, b) = (a.0[0].read(), a.0[1].read());
let (a, b) = (a.get(), b.get());
let a = a let a = a
.as_any() .as_any()
.downcast_ref::<data::string::String>() .downcast_ref::<data::string::String>()

View File

@@ -74,7 +74,8 @@ impl Config {
}, |a, _| { }, |a, _| {
let a = a.get(); let a = a.get();
let a = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let a = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
let (v, e) = (a.0[0].get(), a.0[1].get()); let (v, e) = (a.0[0].read(), a.0[1].read());
let (v, e) = (v.get(), e.get());
let (v, e) = (v.as_any().downcast_ref::<data::int::Int>().unwrap(), e.as_any().downcast_ref::<data::int::Int>().unwrap()); let (v, e) = (v.as_any().downcast_ref::<data::int::Int>().unwrap(), e.as_any().downcast_ref::<data::int::Int>().unwrap());
Ok(Data::new(Range(v.0, e.0))) Ok(Data::new(Range(v.0, e.0)))
} }
@@ -114,7 +115,8 @@ impl Config {
}, |a, _| { }, |a, _| {
let a = a.get(); let a = a.get();
let a = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let a = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
let (v, e) = (a.0[0].get(), a.0[1].get()); let (v, e) = (a.0[0].read(), a.0[1].read());
let (v, e) = (v.get(), e.get());
let (v, e) = (v.as_any().downcast_ref::<data::int::Int>().unwrap(), e.as_any().downcast_ref::<data::int::Int>().unwrap()); let (v, e) = (v.as_any().downcast_ref::<data::int::Int>().unwrap(), e.as_any().downcast_ref::<data::int::Int>().unwrap());
if let Some(e) = e.0.checked_sub(1) { if let Some(e) = e.0.checked_sub(1) {
Ok(Data::new(Range(v.0, e))) Ok(Data::new(Range(v.0, e)))
@@ -495,7 +497,7 @@ impl MersData for Iter {
.iterable(&gi)? .iterable(&gi)?
.enumerate() .enumerate()
.map(|(i, v)| match v { .map(|(i, v)| match v {
Ok(v) => Ok(Data::new(data::tuple::Tuple(vec![ Ok(v) => Ok(Data::new(data::tuple::Tuple::from([
Data::new(data::int::Int(i as _)), Data::new(data::int::Int(i as _)),
v, v,
]))), ]))),

View File

@@ -65,9 +65,7 @@ impl Config {
.as_any() .as_any()
.downcast_ref::<data::reference::Reference>() .downcast_ref::<data::reference::Reference>()
.unwrap() .unwrap()
.0
.write() .write()
.unwrap()
.get_mut() .get_mut()
.mut_any() .mut_any()
.downcast_mut::<List>() .downcast_mut::<List>()
@@ -128,20 +126,18 @@ impl Config {
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let tuple = a.get(); let tuple = a.get();
let tuple = tuple.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let tuple = tuple.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
tuple.0[0] tuple.0[0].read()
.get() .get()
.as_any() .as_any()
.downcast_ref::<data::reference::Reference>() .downcast_ref::<data::reference::Reference>()
.unwrap() .unwrap()
.0
.write() .write()
.unwrap()
.get_mut() .get_mut()
.mut_any() .mut_any()
.downcast_mut::<List>() .downcast_mut::<List>()
.unwrap() .unwrap()
.0 .0
.push(tuple.0[1].clone()); .push(tuple.0[1].read().clone());
Ok(Data::empty_tuple()) Ok(Data::empty_tuple())
}), }),
inner_statements: None, inner_statements: None,
@@ -197,15 +193,14 @@ impl Config {
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let tuple = a.get(); let tuple = a.get();
let tuple = tuple.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let tuple = tuple.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
let index = tuple.0[1].get().as_any().downcast_ref::<data::int::Int>().unwrap().0 as usize; let index = tuple.0[1].read().get().as_any().downcast_ref::<data::int::Int>().unwrap().0 as usize;
let list = tuple.0[0] let list = tuple.0[0].read();
.get(); let list = list.get();
let mut list = list let mut list = list
.as_any() .as_any()
.downcast_ref::<data::reference::Reference>() .downcast_ref::<data::reference::Reference>()
.unwrap() .unwrap()
.0 .write();
.write().unwrap();
let mut list = list let mut list = list
.get_mut(); .get_mut();
let list = list let list = list
@@ -215,7 +210,7 @@ impl Config {
if index > list.0.len() { if index > list.0.len() {
Ok(Data::new(data::bool::Bool(false))) Ok(Data::new(data::bool::Bool(false)))
} else { } else {
list.0.insert(index, tuple.0[2].clone()); list.0.insert(index, tuple.0[2].read().clone());
Ok(Data::new(data::bool::Bool(true))) Ok(Data::new(data::bool::Bool(true)))
} }
}), }),
@@ -277,15 +272,14 @@ impl Config {
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let tuple = a.get(); let tuple = a.get();
let tuple = tuple.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let tuple = tuple.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
let index = tuple.0[1].get().as_any().downcast_ref::<data::int::Int>().unwrap().0 as usize; let index = tuple.0[1].read().get().as_any().downcast_ref::<data::int::Int>().unwrap().0 as usize;
let list = tuple.0[0] let list = tuple.0[0].read();
.get(); let list = list.get();
let mut list = list let mut list = list
.as_any() .as_any()
.downcast_ref::<data::reference::Reference>() .downcast_ref::<data::reference::Reference>()
.unwrap() .unwrap()
.0 .write();
.write().unwrap();
let mut list = list let mut list = list
.get_mut(); .get_mut();
let list = list let list = list
@@ -293,7 +287,7 @@ impl Config {
.downcast_mut::<List>() .downcast_mut::<List>()
.unwrap(); .unwrap();
if index < list.0.len() { if index < list.0.len() {
Ok(Data::one_tuple(std::mem::replace(&mut list.0[index], tuple.0[2].clone()))) Ok(Data::one_tuple(std::mem::replace(&mut list.0[index], tuple.0[2].read().clone())))
} else { } else {
Ok(Data::empty_tuple()) Ok(Data::empty_tuple())
} }
@@ -350,15 +344,14 @@ impl Config {
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
let tuple = a.get(); let tuple = a.get();
let tuple = tuple.as_any().downcast_ref::<data::tuple::Tuple>().unwrap(); let tuple = tuple.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
let index = tuple.0[1].get().as_any().downcast_ref::<data::int::Int>().unwrap().0 as usize; let index = tuple.0[1].read().get().as_any().downcast_ref::<data::int::Int>().unwrap().0 as usize;
let list = tuple.0[0] let list = tuple.0[0].read();
.get(); let list = list.get();
let mut list = list let mut list = list
.as_any() .as_any()
.downcast_ref::<data::reference::Reference>() .downcast_ref::<data::reference::Reference>()
.unwrap() .unwrap()
.0 .write();
.write().unwrap();
let mut list = list let mut list = list
.get_mut(); .get_mut();
let list = list let list = list

View File

@@ -805,7 +805,7 @@ fn func_math_op(
.map(|v| &v.0) .map(|v| &v.0)
.filter(|v| v.len() == 2) .filter(|v| v.len() == 2)
{ {
let (a, b) = (&a[0], &a[1]); let (a, b) = (&a[0].read(), &a[1].read());
let (a, b) = (a.get(), b.get()); let (a, b) = (a.get(), b.get());
let a = a let a = a
.as_any() .as_any()

View File

@@ -30,7 +30,7 @@ impl MersStatement for Block {
.iter() .iter()
.map(|s| s.run(info)) .map(|s| s.run(info))
.last() .last()
.unwrap_or_else(|| Ok(Data::new(data::tuple::Tuple(vec![])))) .unwrap_or_else(|| Ok(Data::new(data::tuple::Tuple::empty())))
} }
fn has_scope(&self) -> bool { fn has_scope(&self) -> bool {
true true

View File

@@ -95,7 +95,7 @@ impl MersStatement for FieldChain {
.as_any() .as_any()
.downcast_ref::<data::reference::Reference>() .downcast_ref::<data::reference::Reference>()
{ {
obj_ref = r.0.read().unwrap(); obj_ref = r.read();
obj_in_ref = obj_ref.get(); obj_in_ref = obj_ref.get();
obj_in_ref.as_any().downcast_ref::<data::object::Object>() obj_in_ref.as_any().downcast_ref::<data::object::Object>()
} else { } else {
@@ -126,7 +126,7 @@ impl MersStatement for FieldChain {
for res in more_args.iter().map(|arg| arg.run(info)) { for res in more_args.iter().map(|arg| arg.run(info)) {
args.push(res?); args.push(res?);
} }
Data::new(Tuple(args)) Data::new(Tuple::from(args))
} else { } else {
object object
}; };

View File

@@ -1,7 +1,7 @@
use std::collections::HashMap; use std::{collections::HashMap, sync::Arc};
use crate::{ use crate::{
data::{self, object::ObjectT, Data, Type}, data::{self, object::ObjectT, reference::ReferenceT, Data, Type},
errors::{CheckError, EColor, SourceRange}, errors::{CheckError, EColor, SourceRange},
}; };
@@ -23,7 +23,19 @@ impl MersStatement for Object {
init_to_is_empty_type = init_to.types.is_empty(); init_to_is_empty_type = init_to.types.is_empty();
let print_is_part_of = init_to.types.len() > 1; let print_is_part_of = init_to.types.len() > 1;
let mut init_fields = HashMap::new(); let mut init_fields = HashMap::new();
for t in init_to.types.iter() { for (t, init_to_ref) in init_to
.types
.iter()
.filter_map(|t| t.as_any().downcast_ref::<ReferenceT>())
.flat_map(|r| r.0.types.iter().map(|t| (t, true)))
.chain(
init_to
.types
.iter()
.filter(|t| !t.as_any().is::<ReferenceT>())
.map(|t| (t, false)),
)
{
if let Some(ot) = t.as_any().downcast_ref::<ObjectT>() { if let Some(ot) = t.as_any().downcast_ref::<ObjectT>() {
let mut fields = self.fields.iter().map(|(t, _)| *t).collect::<Vec<_>>(); let mut fields = self.fields.iter().map(|(t, _)| *t).collect::<Vec<_>>();
fields.sort(); fields.sort();
@@ -31,10 +43,12 @@ impl MersStatement for Object {
if let Ok(i) = fields.binary_search(field) { if let Ok(i) = fields.binary_search(field) {
fields.remove(i); fields.remove(i);
} }
init_fields let init_fields = init_fields.entry(*field).or_insert_with(Type::empty);
.entry(*field) if init_to_ref {
.or_insert_with(Type::empty) init_fields.add(Arc::new(ReferenceT(t.clone())));
.add_all(t); } else {
init_fields.add_all(t);
}
} }
if !fields.is_empty() { if !fields.is_empty() {
return Err(CheckError::new().msg(vec![ return Err(CheckError::new().msg(vec![
@@ -136,7 +150,7 @@ impl MersStatement for Object {
self.fields self.fields
.iter() .iter()
.map(|(n, s)| Ok::<_, CheckError>((n.clone(), s.run(info)?))) .map(|(n, s)| Ok::<_, CheckError>((n.clone(), s.run(info)?)))
.collect::<Result<_, _>>()?, .collect::<Result<Vec<_>, _>>()?,
))) )))
} }
fn has_scope(&self) -> bool { fn has_scope(&self) -> bool {

View File

@@ -1,7 +1,7 @@
use std::collections::VecDeque; use std::{collections::VecDeque, sync::Arc};
use crate::{ use crate::{
data::{self, tuple::TupleT, Data, MersType, Type}, data::{self, reference::ReferenceT, tuple::TupleT, Data, MersType, Type},
errors::{CheckError, EColor, SourceRange}, errors::{CheckError, EColor, SourceRange},
}; };
@@ -23,11 +23,27 @@ impl MersStatement for Tuple {
.map(|_| Type::empty()) .map(|_| Type::empty())
.collect::<VecDeque<_>>(); .collect::<VecDeque<_>>();
let print_is_part_of = init_to.types.len() > 1; let print_is_part_of = init_to.types.len() > 1;
for t in init_to.types.iter() { for (t, init_to_ref) in init_to
.types
.iter()
.filter_map(|t| t.as_any().downcast_ref::<ReferenceT>())
.flat_map(|r| r.0.types.iter().map(|t| (t, true)))
.chain(
init_to
.types
.iter()
.filter(|t| !t.as_any().is::<ReferenceT>())
.map(|t| (t, false)),
)
{
if let Some(t) = t.as_any().downcast_ref::<TupleT>() { if let Some(t) = t.as_any().downcast_ref::<TupleT>() {
if t.0.len() == self.elems.len() { if t.0.len() == self.elems.len() {
for (i, e) in t.0.iter().enumerate() { for (i, e) in t.0.iter().enumerate() {
vec[i].add_all(&e); if init_to_ref {
vec[i].add(Arc::new(ReferenceT(e.clone())));
} else {
vec[i].add_all(e);
}
} }
} else { } else {
return Err(CheckError::new().msg(vec![ return Err(CheckError::new().msg(vec![
@@ -102,11 +118,11 @@ impl MersStatement for Tuple {
))) )))
} }
fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> { fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
Ok(Data::new(data::tuple::Tuple( Ok(Data::new(data::tuple::Tuple::from(
self.elems self.elems
.iter() .iter()
.map(|s| Ok(s.run(info)?)) .map(|s| Ok(s.run(info)?))
.collect::<Result<_, CheckError>>()?, .collect::<Result<Vec<_>, CheckError>>()?,
))) )))
} }
fn has_scope(&self) -> bool { fn has_scope(&self) -> bool {

View File

@@ -60,14 +60,14 @@ impl MersStatement for Variable {
info.scopes[self.var.0].vars[self.var.1] = nothing; info.scopes[self.var.0].vars[self.var.1] = nothing;
} else { } else {
// (reference to) data which will never be referenced again // (reference to) data which will never be referenced again
return Ok(Data::new(data::reference::Reference(Arc::new( return Ok(Data::new(data::reference::Reference::from(
RwLock::new(Data::empty_tuple()), Data::empty_tuple(),
)))); )));
} }
} }
Ok(if self.is_ref_not_ignore { Ok(if self.is_ref_not_ignore {
let v = &info.scopes[self.var.0].vars[self.var.1]; let v = &info.scopes[self.var.0].vars[self.var.1];
Data::new(data::reference::Reference(Arc::clone(v))) Data::new(data::reference::Reference::raw(Arc::clone(v)))
} else { } else {
info.scopes[self.var.0].vars[self.var.1] info.scopes[self.var.0].vars[self.var.1]
.write() .write()

View File

@@ -4,7 +4,7 @@ version = "0.9.15"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
mers_lib = "0.9.18" mers_lib = "0.9.28"
lspower = "1.5.0" lspower = "1.5.0"
tokio = { version = "1.36.0", features = ["full"] } tokio = { version = "1.36.0", features = ["full"] }
line-span = "0.1.5" line-span = "0.1.5"