mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
completely changed the VData/VDataEnum system: Multiple VData can share one VDataEnum via an Arc<Mutex<VDataEnum>>. If one wants to modify the data, it copies it (Copy on Write). This copying is skipped for shared mutable data (references). This was necessary for the get_ref() function. Expect bugs!
This commit is contained in:
parent
ceddb886a9
commit
4efee9e2a2
8
get_ref.mers
Normal file
8
get_ref.mers
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
list = [1 2 3 4 5 6 7 8 9 ...]
|
||||||
|
|
||||||
|
second = &list.get_ref(2).assume1()
|
||||||
|
second.debug()
|
||||||
|
*second = 24
|
||||||
|
second.debug()
|
||||||
|
|
||||||
|
list.debug()
|
@ -461,7 +461,7 @@ impl ByteData for VSingleType {
|
|||||||
}
|
}
|
||||||
impl ByteDataA for VData {
|
impl ByteDataA for VData {
|
||||||
fn as_byte_data(&self, vec: &mut Vec<u8>) {
|
fn as_byte_data(&self, vec: &mut Vec<u8>) {
|
||||||
self.data.as_byte_data(vec)
|
self.data().0.as_byte_data(vec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ByteData for VData {
|
impl ByteData for VData {
|
||||||
@ -469,9 +469,7 @@ impl ByteData for VData {
|
|||||||
where
|
where
|
||||||
R: std::io::Read,
|
R: std::io::Read,
|
||||||
{
|
{
|
||||||
Ok(Self {
|
Ok(VDataEnum::from_byte_data(data)?.to())
|
||||||
data: ByteData::from_byte_data(data)?,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ByteDataA for VDataEnum {
|
impl ByteDataA for VDataEnum {
|
||||||
|
@ -910,8 +910,8 @@ pub mod implementation {
|
|||||||
let args = [out].into_iter().chain(args.into_iter()).collect();
|
let args = [out].into_iter().chain(args.into_iter()).collect();
|
||||||
SStatementEnum::FunctionCall(func, args).to()
|
SStatementEnum::FunctionCall(func, args).to()
|
||||||
}
|
}
|
||||||
SStatementEnum::Value(vd) => match vd.data {
|
SStatementEnum::Value(vd) => match &vd.data().0 {
|
||||||
VDataEnum::Int(i) => SStatementEnum::IndexFixed(out, i as _).to(),
|
VDataEnum::Int(i) => SStatementEnum::IndexFixed(out, *i as _).to(),
|
||||||
_ => {
|
_ => {
|
||||||
let mut context = vec![];
|
let mut context = vec![];
|
||||||
if chain_length > 0 {
|
if chain_length > 0 {
|
||||||
|
@ -76,6 +76,7 @@ pub enum BuiltinFunction {
|
|||||||
Pop,
|
Pop,
|
||||||
Remove,
|
Remove,
|
||||||
Get,
|
Get,
|
||||||
|
GetRef,
|
||||||
Len,
|
Len,
|
||||||
// String
|
// String
|
||||||
Contains,
|
Contains,
|
||||||
@ -138,6 +139,7 @@ impl BuiltinFunction {
|
|||||||
"pop" => Self::Pop,
|
"pop" => Self::Pop,
|
||||||
"remove" => Self::Remove,
|
"remove" => Self::Remove,
|
||||||
"get" => Self::Get,
|
"get" => Self::Get,
|
||||||
|
"get_ref" => Self::GetRef,
|
||||||
"len" => Self::Len,
|
"len" => Self::Len,
|
||||||
"contains" => Self::Contains,
|
"contains" => Self::Contains,
|
||||||
"starts_with" => Self::StartsWith,
|
"starts_with" => Self::StartsWith,
|
||||||
@ -443,7 +445,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO! finish this
|
// TODO! finish this
|
||||||
Self::Get | Self::Len => true,
|
Self::Get | Self::GetRef | Self::Len => true,
|
||||||
Self::Substring => {
|
Self::Substring => {
|
||||||
if input.len() >= 2 && input.len() <= 3 {
|
if input.len() >= 2 && input.len() <= 3 {
|
||||||
let (s, start) = (&input[0], &input[1]);
|
let (s, start) = (&input[0], &input[1]);
|
||||||
@ -598,6 +600,26 @@ impl BuiltinFunction {
|
|||||||
unreachable!("get, pop or remove called without args")
|
unreachable!("get, pop or remove called without args")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Self::GetRef => {
|
||||||
|
if let Some(v) = input.first() {
|
||||||
|
VType {
|
||||||
|
types: vec![
|
||||||
|
VSingleType::Tuple(vec![]),
|
||||||
|
VSingleType::Tuple(vec![{
|
||||||
|
let mut v = v.get_any(info).expect("cannot use get on this type");
|
||||||
|
v.types = v
|
||||||
|
.types
|
||||||
|
.into_iter()
|
||||||
|
.map(|v| VSingleType::Reference(Box::new(v)))
|
||||||
|
.collect();
|
||||||
|
v
|
||||||
|
}]),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("get, pop or remove called without args")
|
||||||
|
}
|
||||||
|
}
|
||||||
Self::Exit => VType { types: vec![] }, // doesn't return
|
Self::Exit => VType { types: vec![] }, // doesn't return
|
||||||
Self::FsList => VType {
|
Self::FsList => VType {
|
||||||
types: vec![
|
types: vec![
|
||||||
@ -726,67 +748,87 @@ impl BuiltinFunction {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn run(
|
pub fn run(&self, args: &Vec<RStatement>, vars: &mut Vec<VData>, info: &GSInfo) -> VData {
|
||||||
&self,
|
|
||||||
args: &Vec<RStatement>,
|
|
||||||
vars: &Vec<Arc<Mutex<VData>>>,
|
|
||||||
info: &GSInfo,
|
|
||||||
) -> VData {
|
|
||||||
match self {
|
match self {
|
||||||
Self::Assume1 => match args[0].run(vars, info).data {
|
Self::Assume1 => {
|
||||||
VDataEnum::Tuple(mut v) => {
|
let mut a0 = args[0].run(vars, info);
|
||||||
|
a0.make_mut();
|
||||||
|
let o = match &mut a0.data.lock().unwrap().0 {
|
||||||
|
VDataEnum::Tuple(v) => Some({
|
||||||
if let Some(v) = v.pop() {
|
if let Some(v) = v.pop() {
|
||||||
v
|
v
|
||||||
} else {
|
} else {
|
||||||
panic!(
|
let msg = if args.len() > 1 {
|
||||||
"ASSUMPTION FAILED: assume1 :: {}",
|
let a1 = args[1].run(vars, info);
|
||||||
if args.len() > 1 {
|
let a1 = a1.data();
|
||||||
if let VDataEnum::String(v) = args[1].run(vars, info).data {
|
if let VDataEnum::String(v) = &a1.0 {
|
||||||
v
|
Some(v.to_owned())
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
None
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
None
|
||||||
},
|
};
|
||||||
);
|
if let Some(m) = msg {
|
||||||
|
panic!("ASSUMPTION FAILED: assume1 :: {m}");
|
||||||
|
} else {
|
||||||
|
panic!("ASSUMPTION FAILED: assume1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(o) = o {
|
||||||
|
o
|
||||||
|
} else {
|
||||||
|
a0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v => v.to(),
|
|
||||||
},
|
|
||||||
Self::AssumeNoEnum => {
|
Self::AssumeNoEnum => {
|
||||||
let data = args[0].run(vars, info);
|
let msg = if args.len() > 1 {
|
||||||
match data.data {
|
if let VDataEnum::String(v) = args[1].run(vars, info).inner() {
|
||||||
VDataEnum::EnumVariant(..) => panic!(
|
Some(v.to_owned())
|
||||||
"ASSUMPTION FAILED: assume_no_enum :: found {} :: {}",
|
} else {
|
||||||
data.gsi(info.clone()),
|
None
|
||||||
if args.len() > 1 {
|
}
|
||||||
if let VDataEnum::String(v) = args[1].run(vars, info).data {
|
} else {
|
||||||
v
|
None
|
||||||
|
};
|
||||||
|
let a0 = args[0].run(vars, info);
|
||||||
|
let a0d = a0.data();
|
||||||
|
match &a0d.0 {
|
||||||
|
VDataEnum::EnumVariant(..) => {
|
||||||
|
drop(a0d);
|
||||||
|
panic!(
|
||||||
|
"ASSUMPTION FAILED: assume_no_enum :: found {}{}",
|
||||||
|
a0.gsi(info.clone()),
|
||||||
|
if let Some(m) = msg {
|
||||||
|
format!(" :: {m}")
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
}
|
}
|
||||||
} else {
|
)
|
||||||
String::new()
|
}
|
||||||
|
_ => {
|
||||||
|
drop(a0d);
|
||||||
|
a0
|
||||||
}
|
}
|
||||||
),
|
|
||||||
d => d.to(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::NoEnum => args[0].run(vars, info).noenum(),
|
Self::NoEnum => args[0].run(vars, info).noenum(),
|
||||||
Self::Matches => match args[0].run(vars, info).data.matches() {
|
Self::Matches => match args[0].run(vars, info).inner().matches() {
|
||||||
Some(v) => VDataEnum::Tuple(vec![v]).to(),
|
Some(v) => VDataEnum::Tuple(vec![v]).to(),
|
||||||
None => VDataEnum::Tuple(vec![]).to(),
|
None => VDataEnum::Tuple(vec![]).to(),
|
||||||
},
|
},
|
||||||
Self::Clone => {
|
Self::Clone => {
|
||||||
if let VDataEnum::Reference(r) = args[0].run(vars, info).data {
|
if let VDataEnum::Reference(r) = &args[0].run(vars, info).data().0 {
|
||||||
r.lock().unwrap().clone()
|
r.clone()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BuiltinFunction::Print => {
|
BuiltinFunction::Print => {
|
||||||
if let VDataEnum::String(arg) = args[0].run(vars, info).data {
|
if let VDataEnum::String(arg) = &args[0].run(vars, info).data().0 {
|
||||||
print!("{}", arg);
|
print!("{}", arg);
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
} else {
|
} else {
|
||||||
@ -794,7 +836,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
BuiltinFunction::Println => {
|
BuiltinFunction::Println => {
|
||||||
if let VDataEnum::String(arg) = args[0].run(vars, info).data {
|
if let VDataEnum::String(arg) = &args[0].run(vars, info).data().0 {
|
||||||
#[cfg(not(feature = "nushell_plugin"))]
|
#[cfg(not(feature = "nushell_plugin"))]
|
||||||
println!("{}", arg);
|
println!("{}", arg);
|
||||||
#[cfg(feature = "nushell_plugin")]
|
#[cfg(feature = "nushell_plugin")]
|
||||||
@ -831,13 +873,13 @@ impl BuiltinFunction {
|
|||||||
VDataEnum::String(args[0].run(vars, info).gsi(info.clone()).to_string()).to()
|
VDataEnum::String(args[0].run(vars, info).gsi(info.clone()).to_string()).to()
|
||||||
}
|
}
|
||||||
BuiltinFunction::Format => {
|
BuiltinFunction::Format => {
|
||||||
if let VDataEnum::String(mut text) = args.first().unwrap().run(vars, info).data {
|
if let VDataEnum::String(mut text) = args.first().unwrap().run(vars, info).inner() {
|
||||||
for (i, arg) in args.iter().skip(1).enumerate() {
|
for (i, arg) in args.iter().skip(1).enumerate() {
|
||||||
text = text.replace(
|
text = text.replace(
|
||||||
&format!("{{{i}}}"),
|
&format!("{{{i}}}"),
|
||||||
&format!(
|
&format!(
|
||||||
"{}",
|
"{}",
|
||||||
if let VDataEnum::String(v) = arg.run(vars, info).data {
|
if let VDataEnum::String(v) = &arg.run(vars, info).data().0 {
|
||||||
v
|
v
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@ -852,7 +894,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
BuiltinFunction::ParseInt => {
|
BuiltinFunction::ParseInt => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let VDataEnum::String(s) = args[0].run(vars, info).data {
|
if let VDataEnum::String(s) = &args[0].run(vars, info).data().0 {
|
||||||
if let Ok(s) = s.parse() {
|
if let Ok(s) = s.parse() {
|
||||||
VDataEnum::Int(s).to()
|
VDataEnum::Int(s).to()
|
||||||
} else {
|
} else {
|
||||||
@ -867,7 +909,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
BuiltinFunction::ParseFloat => {
|
BuiltinFunction::ParseFloat => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let VDataEnum::String(s) = args[0].run(vars, info).data {
|
if let VDataEnum::String(s) = &args[0].run(vars, info).data().0 {
|
||||||
if let Ok(s) = s.parse() {
|
if let Ok(s) = s.parse() {
|
||||||
VDataEnum::Float(s).to()
|
VDataEnum::Float(s).to()
|
||||||
} else {
|
} else {
|
||||||
@ -882,13 +924,13 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
BuiltinFunction::Run => {
|
BuiltinFunction::Run => {
|
||||||
if args.len() >= 1 {
|
if args.len() >= 1 {
|
||||||
if let VDataEnum::Function(f) = args[0].run(vars, info).data {
|
if let VDataEnum::Function(f) = &args[0].run(vars, info).data().0 {
|
||||||
if f.inputs.len() != args.len() - 1 {
|
if f.inputs.len() != args.len() - 1 {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
for (i, var) in f.inputs.iter().enumerate() {
|
for (i, var) in f.inputs.iter().enumerate() {
|
||||||
let val = args[i + 1].run(vars, info);
|
let val = args[i + 1].run(vars, info);
|
||||||
*vars[*var].lock().unwrap() = val;
|
vars[*var] = val;
|
||||||
}
|
}
|
||||||
f.run(vars, info)
|
f.run(vars, info)
|
||||||
} else {
|
} else {
|
||||||
@ -900,7 +942,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
BuiltinFunction::Thread => {
|
BuiltinFunction::Thread => {
|
||||||
if args.len() >= 1 {
|
if args.len() >= 1 {
|
||||||
if let VDataEnum::Function(f) = args[0].run(vars, info).data {
|
if let VDataEnum::Function(f) = args[0].run(vars, info).inner() {
|
||||||
if f.inputs.len() != args.len() - 1 {
|
if f.inputs.len() != args.len() - 1 {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@ -910,13 +952,13 @@ impl BuiltinFunction {
|
|||||||
for (i, var) in f.inputs.iter().enumerate() {
|
for (i, var) in f.inputs.iter().enumerate() {
|
||||||
let val = args[i + 1].run(vars, info);
|
let val = args[i + 1].run(vars, info);
|
||||||
run_input_types.push(val.out_single());
|
run_input_types.push(val.out_single());
|
||||||
thread_vars[*var] = Arc::new(Mutex::new(val));
|
thread_vars[*var] = val;
|
||||||
}
|
}
|
||||||
let out_type = f.out(&run_input_types);
|
let out_type = f.out(&run_input_types);
|
||||||
let libs = info.clone();
|
let libs = info.clone();
|
||||||
VDataEnum::Thread(
|
VDataEnum::Thread(
|
||||||
VDataThreadEnum::Running(std::thread::spawn(move || {
|
VDataThreadEnum::Running(std::thread::spawn(move || {
|
||||||
f.run(&thread_vars, &libs)
|
f.run(&mut thread_vars, &libs)
|
||||||
}))
|
}))
|
||||||
.to(),
|
.to(),
|
||||||
out_type,
|
out_type,
|
||||||
@ -931,7 +973,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
BuiltinFunction::Await => {
|
BuiltinFunction::Await => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let VDataEnum::Thread(t, _) = args[0].run(vars, info).data {
|
if let VDataEnum::Thread(t, _) = &args[0].run(vars, info).data().0 {
|
||||||
t.get()
|
t.get()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@ -942,9 +984,9 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
BuiltinFunction::Sleep => {
|
BuiltinFunction::Sleep => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
match args[0].run(vars, info).data {
|
match &args[0].run(vars, info).data().0 {
|
||||||
VDataEnum::Int(v) => std::thread::sleep(Duration::from_secs(v as _)),
|
VDataEnum::Int(v) => std::thread::sleep(Duration::from_secs(*v as _)),
|
||||||
VDataEnum::Float(v) => std::thread::sleep(Duration::from_secs_f64(v)),
|
VDataEnum::Float(v) => std::thread::sleep(Duration::from_secs_f64(*v)),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
@ -954,8 +996,8 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Exit => {
|
Self::Exit => {
|
||||||
if let Some(s) = args.first() {
|
if let Some(s) = args.first() {
|
||||||
if let VDataEnum::Int(v) = s.run(vars, info).data {
|
if let VDataEnum::Int(v) = &s.run(vars, info).data().0 {
|
||||||
std::process::exit(v as _);
|
std::process::exit(*v as _);
|
||||||
} else {
|
} else {
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
@ -965,7 +1007,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::FsList => {
|
Self::FsList => {
|
||||||
if args.len() > 0 {
|
if args.len() > 0 {
|
||||||
if let VDataEnum::String(path) = args[0].run(vars, info).data {
|
if let VDataEnum::String(path) = &args[0].run(vars, info).data().0 {
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
eprintln!("NOT YET IMPLEMENTED (TODO!): fs_list advanced filters")
|
eprintln!("NOT YET IMPLEMENTED (TODO!): fs_list advanced filters")
|
||||||
}
|
}
|
||||||
@ -1003,7 +1045,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::FsRead => {
|
Self::FsRead => {
|
||||||
if args.len() > 0 {
|
if args.len() > 0 {
|
||||||
if let VDataEnum::String(path) = args[0].run(vars, info).data {
|
if let VDataEnum::String(path) = &args[0].run(vars, info).data().0 {
|
||||||
match std::fs::read(path) {
|
match std::fs::read(path) {
|
||||||
Ok(data) => VDataEnum::List(
|
Ok(data) => VDataEnum::List(
|
||||||
VSingleType::Int.into(),
|
VSingleType::Int.into(),
|
||||||
@ -1027,9 +1069,10 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::FsWrite => {
|
Self::FsWrite => {
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
if let (VDataEnum::String(path), VDataEnum::List(_, data)) =
|
if let (VDataEnum::String(path), VDataEnum::List(_, data)) = (
|
||||||
(args[0].run(vars, info).data, args[1].run(vars, info).data)
|
&args[0].run(vars, info).data().0,
|
||||||
{
|
&args[1].run(vars, info).data().0,
|
||||||
|
) {
|
||||||
if let Some(bytes) = vdata_to_bytes(&data) {
|
if let Some(bytes) = vdata_to_bytes(&data) {
|
||||||
let file_path: PathBuf = path.into();
|
let file_path: PathBuf = path.into();
|
||||||
if let Some(p) = file_path.parent() {
|
if let Some(p) = file_path.parent() {
|
||||||
@ -1057,7 +1100,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::BytesToString => {
|
Self::BytesToString => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let VDataEnum::List(_, byte_data) = args[0].run(vars, info).data {
|
if let VDataEnum::List(_, byte_data) = &args[0].run(vars, info).data().0 {
|
||||||
if let Some(bytes) = vdata_to_bytes(&byte_data) {
|
if let Some(bytes) = vdata_to_bytes(&byte_data) {
|
||||||
match String::from_utf8(bytes) {
|
match String::from_utf8(bytes) {
|
||||||
Ok(v) => VDataEnum::String(v).to(),
|
Ok(v) => VDataEnum::String(v).to(),
|
||||||
@ -1092,7 +1135,7 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::StringToBytes => {
|
Self::StringToBytes => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let VDataEnum::String(s) = args[0].run(vars, info).data {
|
if let VDataEnum::String(s) = &args[0].run(vars, info).data().0 {
|
||||||
VDataEnum::List(
|
VDataEnum::List(
|
||||||
VSingleType::Int.into(),
|
VSingleType::Int.into(),
|
||||||
s.bytes().map(|v| VDataEnum::Int(v as isize).to()).collect(),
|
s.bytes().map(|v| VDataEnum::Int(v as isize).to()).collect(),
|
||||||
@ -1107,12 +1150,12 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::RunCommand | Self::RunCommandGetBytes => {
|
Self::RunCommand | Self::RunCommandGetBytes => {
|
||||||
if args.len() > 0 {
|
if args.len() > 0 {
|
||||||
if let VDataEnum::String(s) = args[0].run(vars, info).data {
|
if let VDataEnum::String(s) = &args[0].run(vars, info).data().0 {
|
||||||
let mut command = std::process::Command::new(s);
|
let mut command = std::process::Command::new(s);
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
if let VDataEnum::List(_, args) = args[1].run(vars, info).data {
|
if let VDataEnum::List(_, args) = &args[1].run(vars, info).data().0 {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
if let VDataEnum::String(v) = arg.data {
|
if let VDataEnum::String(v) = &arg.data().0 {
|
||||||
command.arg(v);
|
command.arg(v);
|
||||||
} else {
|
} else {
|
||||||
unreachable!("run_command second arg not [string].")
|
unreachable!("run_command second arg not [string].")
|
||||||
@ -1172,19 +1215,19 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Not => {
|
Self::Not => {
|
||||||
if let VDataEnum::Bool(v) = args[0].run(vars, info).data {
|
if let VDataEnum::Bool(v) = &args[0].run(vars, info).data().0 {
|
||||||
VDataEnum::Bool(!v).to()
|
VDataEnum::Bool(!v).to()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::And => {
|
Self::And => {
|
||||||
if let VDataEnum::Bool(a) = args[0].run(vars, info).data {
|
if let VDataEnum::Bool(a) = &args[0].run(vars, info).data().0 {
|
||||||
if a == false {
|
if *a == false {
|
||||||
VDataEnum::Bool(false).to()
|
VDataEnum::Bool(false).to()
|
||||||
} else {
|
} else {
|
||||||
if let VDataEnum::Bool(b) = args[1].run(vars, info).data {
|
if let VDataEnum::Bool(b) = &args[1].run(vars, info).data().0 {
|
||||||
VDataEnum::Bool(b).to()
|
VDataEnum::Bool(*b).to()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@ -1194,12 +1237,12 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Or => {
|
Self::Or => {
|
||||||
if let VDataEnum::Bool(a) = args[0].run(vars, info).data {
|
if let VDataEnum::Bool(a) = &args[0].run(vars, info).data().0 {
|
||||||
if a == true {
|
if *a == true {
|
||||||
VDataEnum::Bool(true).to()
|
VDataEnum::Bool(true).to()
|
||||||
} else {
|
} else {
|
||||||
if let VDataEnum::Bool(b) = args[1].run(vars, info).data {
|
if let VDataEnum::Bool(b) = &args[1].run(vars, info).data().0 {
|
||||||
VDataEnum::Bool(b).to()
|
VDataEnum::Bool(*b).to()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@ -1210,7 +1253,10 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Add => {
|
Self::Add => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
match (
|
||||||
|
args[0].run(vars, info).inner(),
|
||||||
|
args[1].run(vars, info).inner(),
|
||||||
|
) {
|
||||||
(VDataEnum::String(mut a), VDataEnum::String(b)) => {
|
(VDataEnum::String(mut a), VDataEnum::String(b)) => {
|
||||||
a.push_str(b.as_str());
|
a.push_str(b.as_str());
|
||||||
VDataEnum::String(a).to()
|
VDataEnum::String(a).to()
|
||||||
@ -1231,13 +1277,16 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Sub => {
|
Self::Sub => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
match (
|
||||||
|
&args[0].run(vars, info).data().0,
|
||||||
|
&args[1].run(vars, info).data().0,
|
||||||
|
) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a - b).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a - b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float(a as f64 - b).to()
|
VDataEnum::Float(*a as f64 - *b).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
VDataEnum::Float(a - b as f64).to()
|
VDataEnum::Float(*a - *b as f64).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a - b).to(),
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a - b).to(),
|
||||||
_ => unreachable!("sub: not a number"),
|
_ => unreachable!("sub: not a number"),
|
||||||
@ -1248,13 +1297,16 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Mul => {
|
Self::Mul => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
match (
|
||||||
|
&args[0].run(vars, info).data().0,
|
||||||
|
&args[1].run(vars, info).data().0,
|
||||||
|
) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a * b).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a * b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float(a as f64 * b).to()
|
VDataEnum::Float(*a as f64 * b).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
VDataEnum::Float(a * b as f64).to()
|
VDataEnum::Float(a * *b as f64).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a * b).to(),
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a * b).to(),
|
||||||
_ => unreachable!("mul: not a number"),
|
_ => unreachable!("mul: not a number"),
|
||||||
@ -1265,13 +1317,16 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Div => {
|
Self::Div => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
match (
|
||||||
|
&args[0].run(vars, info).data().0,
|
||||||
|
&args[1].run(vars, info).data().0,
|
||||||
|
) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a / b).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a / b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float(a as f64 / b).to()
|
VDataEnum::Float(*a as f64 / b).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
VDataEnum::Float(a / b as f64).to()
|
VDataEnum::Float(a / *b as f64).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a / b).to(),
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a / b).to(),
|
||||||
_ => unreachable!("div: not a number"),
|
_ => unreachable!("div: not a number"),
|
||||||
@ -1282,13 +1337,16 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Mod => {
|
Self::Mod => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
match (
|
||||||
|
&args[0].run(vars, info).data().0,
|
||||||
|
&args[1].run(vars, info).data().0,
|
||||||
|
) {
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a % b).to(),
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a % b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float(a as f64 % b).to()
|
VDataEnum::Float(*a as f64 % b).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
VDataEnum::Float(a % b as f64).to()
|
VDataEnum::Float(a % *b as f64).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a % b).to(),
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a % b).to(),
|
||||||
_ => unreachable!("mod: not a number"),
|
_ => unreachable!("mod: not a number"),
|
||||||
@ -1299,23 +1357,26 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Pow => {
|
Self::Pow => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
match (
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(if b == 0 {
|
&args[0].run(vars, info).data().0,
|
||||||
|
&args[1].run(vars, info).data().0,
|
||||||
|
) {
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(if *b == 0 {
|
||||||
1
|
1
|
||||||
} else if b > 0 {
|
} else if *b > 0 {
|
||||||
a.pow(b as _)
|
(*a).pow(*b as _)
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
})
|
})
|
||||||
.to(),
|
.to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float((a as f64).powf(b)).to()
|
VDataEnum::Float((*a as f64).powf(*b)).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
VDataEnum::Float(a.powi(b as _)).to()
|
VDataEnum::Float((*a).powi(*b as _)).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float(a.powf(b)).to()
|
VDataEnum::Float((*a).powf(*b)).to()
|
||||||
}
|
}
|
||||||
_ => unreachable!("pow: not a number"),
|
_ => unreachable!("pow: not a number"),
|
||||||
}
|
}
|
||||||
@ -1332,15 +1393,18 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Gt => {
|
Self::Gt => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
match (
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a > b).to(),
|
&args[0].run(vars, info).data().0,
|
||||||
|
&args[1].run(vars, info).data().0,
|
||||||
|
) {
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(*a > *b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Bool(a as f64 > b).to()
|
VDataEnum::Bool(*a as f64 > *b).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
VDataEnum::Bool(a > b as f64).to()
|
VDataEnum::Bool(*a > *b as f64).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Bool(a > b).to(),
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Bool(*a > *b).to(),
|
||||||
_ => unreachable!("gt: not a number"),
|
_ => unreachable!("gt: not a number"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1349,15 +1413,18 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Lt => {
|
Self::Lt => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
match (
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a < b).to(),
|
&args[0].run(vars, info).data().0,
|
||||||
|
&args[1].run(vars, info).data().0,
|
||||||
|
) {
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(*a < *b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Bool((a as f64) < b).to()
|
VDataEnum::Bool((*a as f64) < *b).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
VDataEnum::Bool(a < b as f64).to()
|
VDataEnum::Bool(*a < *b as f64).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Bool(a < b).to(),
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Bool(*a < *b).to(),
|
||||||
_ => unreachable!("lt: not a number"),
|
_ => unreachable!("lt: not a number"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1366,15 +1433,20 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Gtoe => {
|
Self::Gtoe => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
match (
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a >= b).to(),
|
&args[0].run(vars, info).data().0,
|
||||||
|
&args[1].run(vars, info).data().0,
|
||||||
|
) {
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(*a >= *b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Bool(a as f64 >= b).to()
|
VDataEnum::Bool(*a as f64 >= *b).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
VDataEnum::Bool(a >= b as f64).to()
|
VDataEnum::Bool(*a >= *b as f64).to()
|
||||||
|
}
|
||||||
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => {
|
||||||
|
VDataEnum::Bool(*a >= *b).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Bool(a >= b).to(),
|
|
||||||
_ => unreachable!("gtoe: not a number"),
|
_ => unreachable!("gtoe: not a number"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1383,15 +1455,20 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Ltoe => {
|
Self::Ltoe => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
match (
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(a <= b).to(),
|
&args[0].run(vars, info).data().0,
|
||||||
|
&args[1].run(vars, info).data().0,
|
||||||
|
) {
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Bool(*a <= *b).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Bool(a as f64 <= b).to()
|
VDataEnum::Bool(*a as f64 <= *b).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
VDataEnum::Bool(a <= b as f64).to()
|
VDataEnum::Bool(*a <= *b as f64).to()
|
||||||
|
}
|
||||||
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => {
|
||||||
|
VDataEnum::Bool(*a <= *b).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Bool(a <= b).to(),
|
|
||||||
_ => unreachable!("ltoe: not a number"),
|
_ => unreachable!("ltoe: not a number"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1400,16 +1477,19 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Min => {
|
Self::Min => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
match (
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a.min(b)).to(),
|
&args[0].run(vars, info).data().0,
|
||||||
|
&args[1].run(vars, info).data().0,
|
||||||
|
) {
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int((*a).min(*b)).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float((a as f64).min(b)).to()
|
VDataEnum::Float((*a as f64).min(*b)).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
VDataEnum::Float(a.min(b as f64)).to()
|
VDataEnum::Float((*a).min(*b as f64)).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float(a.min(b)).to()
|
VDataEnum::Float((*a).min(*b)).to()
|
||||||
}
|
}
|
||||||
_ => unreachable!("min: not a number"),
|
_ => unreachable!("min: not a number"),
|
||||||
}
|
}
|
||||||
@ -1419,16 +1499,19 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Max => {
|
Self::Max => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
match (args[0].run(vars, info).data, args[1].run(vars, info).data) {
|
match (
|
||||||
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a.max(b)).to(),
|
&args[0].run(vars, info).data().0,
|
||||||
|
&args[1].run(vars, info).data().0,
|
||||||
|
) {
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int((*a).max(*b)).to(),
|
||||||
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float((a as f64).max(b)).to()
|
VDataEnum::Float((*a as f64).max(*b)).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
VDataEnum::Float(a.max(b as f64)).to()
|
VDataEnum::Float((*a).max(*b as f64)).to()
|
||||||
}
|
}
|
||||||
(VDataEnum::Float(a), VDataEnum::Float(b)) => {
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => {
|
||||||
VDataEnum::Float(a.max(b)).to()
|
VDataEnum::Float((*a).max(*b)).to()
|
||||||
}
|
}
|
||||||
_ => unreachable!("max: not a number"),
|
_ => unreachable!("max: not a number"),
|
||||||
}
|
}
|
||||||
@ -1438,8 +1521,9 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Push => {
|
Self::Push => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
if let VDataEnum::Reference(v) = args[0].run(vars, info).data {
|
// Since this is a reference, it is safe to assume that make_mut() would do nothing.
|
||||||
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
if let VDataEnum::Reference(v) = &args[0].run(vars, info).data().0 {
|
||||||
|
if let VDataEnum::List(_, v) = &mut v.data().0 {
|
||||||
v.push(args[1].run(vars, info));
|
v.push(args[1].run(vars, info));
|
||||||
}
|
}
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
@ -1452,11 +1536,13 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Insert => {
|
Self::Insert => {
|
||||||
if args.len() == 3 {
|
if args.len() == 3 {
|
||||||
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) =
|
// this being a reference means we wont need to call make_mut() later, so a .as_ref() borrow is enough.
|
||||||
(args[0].run(vars, info).data, args[2].run(vars, info).data)
|
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) = (
|
||||||
{
|
&args[0].run(vars, info).data().0,
|
||||||
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
&args[2].run(vars, info).data().0,
|
||||||
v.insert(i as _, args[1].run(vars, info));
|
) {
|
||||||
|
if let VDataEnum::List(_, v) = &mut v.data().0 {
|
||||||
|
v.insert(*i as _, args[1].run(vars, info));
|
||||||
}
|
}
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
} else {
|
} else {
|
||||||
@ -1468,8 +1554,9 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Pop => {
|
Self::Pop => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let VDataEnum::Reference(v) = args[0].run(vars, info).data {
|
// this being a reference means we wont need to call make_mut() later, so a .as_ref() borrow is enough.
|
||||||
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
if let VDataEnum::Reference(v) = &args[0].run(vars, info).data().0 {
|
||||||
|
if let VDataEnum::List(_, v) = &mut v.data.lock().unwrap().0 {
|
||||||
if let Some(v) = v.pop() {
|
if let Some(v) = v.pop() {
|
||||||
VDataEnum::Tuple(vec![v])
|
VDataEnum::Tuple(vec![v])
|
||||||
} else {
|
} else {
|
||||||
@ -1488,12 +1575,14 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Remove => {
|
Self::Remove => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) =
|
// this being a reference means we wont need to call make_mut() later, so a .as_ref() borrow is enough.
|
||||||
(args[0].run(vars, info).data, args[1].run(vars, info).data)
|
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) = (
|
||||||
{
|
&args[0].run(vars, info).data().0,
|
||||||
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
&args[1].run(vars, info).data().0,
|
||||||
if v.len() > i as _ && i >= 0 {
|
) {
|
||||||
let v = v.remove(i as _);
|
if let VDataEnum::List(_, v) = &mut v.data.lock().unwrap().0 {
|
||||||
|
if *i >= 0 && v.len() > *i as _ {
|
||||||
|
let v = v.remove(*i as _);
|
||||||
VDataEnum::Tuple(vec![v]).to()
|
VDataEnum::Tuple(vec![v]).to()
|
||||||
} else {
|
} else {
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
@ -1510,21 +1599,22 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Get => {
|
Self::Get => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
if let (container, VDataEnum::Int(i)) =
|
if let (container, VDataEnum::Int(i)) = (
|
||||||
(args[0].run(vars, info).data, args[1].run(vars, info).data)
|
&args[0].run(vars, info).data().0,
|
||||||
{
|
&args[1].run(vars, info).data().0,
|
||||||
if i >= 0 {
|
) {
|
||||||
|
if *i >= 0 {
|
||||||
match match container {
|
match match container {
|
||||||
VDataEnum::Reference(v) => match &v.lock().unwrap().data {
|
VDataEnum::Reference(v) => match &v.data().0 {
|
||||||
VDataEnum::List(_, v) | VDataEnum::Tuple(v) => {
|
VDataEnum::List(_, v) | VDataEnum::Tuple(v) => {
|
||||||
v.get(i as usize).map(|v| v.clone())
|
v.get(*i as usize).map(|v| v.clone())
|
||||||
}
|
}
|
||||||
_ => unreachable!(
|
_ => unreachable!(
|
||||||
"get: reference to something other than list/tuple"
|
"get: reference to something other than list/tuple"
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
VDataEnum::List(_, v) | VDataEnum::Tuple(v) => {
|
VDataEnum::List(_, v) | VDataEnum::Tuple(v) => {
|
||||||
v.get(i as usize).map(|v| v.clone())
|
v.get(*i as usize).map(|v| v.clone())
|
||||||
}
|
}
|
||||||
_ => unreachable!("get: not a reference/list/tuple"),
|
_ => unreachable!("get: not a reference/list/tuple"),
|
||||||
} {
|
} {
|
||||||
@ -1541,9 +1631,40 @@ impl BuiltinFunction {
|
|||||||
unreachable!("get: not 2 args")
|
unreachable!("get: not 2 args")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Self::GetRef => {
|
||||||
|
if args.len() == 2 {
|
||||||
|
if let (VDataEnum::Reference(container), VDataEnum::Int(i)) = (
|
||||||
|
&args[0].run(vars, info).data().0,
|
||||||
|
&args[1].run(vars, info).data().0,
|
||||||
|
) {
|
||||||
|
if *i >= 0 {
|
||||||
|
// we can get mutably because this is the content of a reference
|
||||||
|
match match &mut container.data().0 {
|
||||||
|
VDataEnum::List(_, v) | VDataEnum::Tuple(v) => {
|
||||||
|
if let Some(v) = v.get_mut(*i as usize) {
|
||||||
|
Some(VDataEnum::Reference(v.clone_mut()).to())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!("get: not a reference/list/tuple"),
|
||||||
|
} {
|
||||||
|
Some(v) => VDataEnum::Tuple(vec![v]).to(),
|
||||||
|
None => VDataEnum::Tuple(vec![]).to(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
VDataEnum::Tuple(vec![]).to()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("get_ref: not a reference and index")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("get: not 2 args")
|
||||||
|
}
|
||||||
|
}
|
||||||
Self::Len => {
|
Self::Len => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
VDataEnum::Int(match args[0].run(vars, info).data {
|
VDataEnum::Int(match &args[0].run(vars, info).data().0 {
|
||||||
VDataEnum::String(v) => v.len(),
|
VDataEnum::String(v) => v.len(),
|
||||||
VDataEnum::Tuple(v) => v.len(),
|
VDataEnum::Tuple(v) => v.len(),
|
||||||
VDataEnum::List(_, v) => v.len(),
|
VDataEnum::List(_, v) => v.len(),
|
||||||
@ -1556,8 +1677,8 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Contains => {
|
Self::Contains => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
if let VDataEnum::String(a1) = args[0].run(vars, info).data {
|
if let VDataEnum::String(a1) = &args[0].run(vars, info).data().0 {
|
||||||
if let VDataEnum::String(a2) = args[1].run(vars, info).data {
|
if let VDataEnum::String(a2) = &args[1].run(vars, info).data().0 {
|
||||||
VDataEnum::Bool(a1.contains(a2.as_str())).to()
|
VDataEnum::Bool(a1.contains(a2.as_str())).to()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@ -1571,8 +1692,8 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::StartsWith => {
|
Self::StartsWith => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
if let VDataEnum::String(a1) = args[0].run(vars, info).data {
|
if let VDataEnum::String(a1) = &args[0].run(vars, info).data().0 {
|
||||||
if let VDataEnum::String(a2) = args[1].run(vars, info).data {
|
if let VDataEnum::String(a2) = &args[1].run(vars, info).data().0 {
|
||||||
VDataEnum::Bool(a1.starts_with(a2.as_str())).to()
|
VDataEnum::Bool(a1.starts_with(a2.as_str())).to()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@ -1586,8 +1707,8 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::EndsWith => {
|
Self::EndsWith => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
if let VDataEnum::String(a1) = args[0].run(vars, info).data {
|
if let VDataEnum::String(a1) = &args[0].run(vars, info).data().0 {
|
||||||
if let VDataEnum::String(a2) = args[1].run(vars, info).data {
|
if let VDataEnum::String(a2) = &args[1].run(vars, info).data().0 {
|
||||||
VDataEnum::Bool(a1.ends_with(a2.as_str())).to()
|
VDataEnum::Bool(a1.ends_with(a2.as_str())).to()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@ -1622,41 +1743,38 @@ impl BuiltinFunction {
|
|||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match (find_in.data, pat.data) {
|
let o = match (&find_in.data().0, &pat.data().0) {
|
||||||
(VDataEnum::String(a), VDataEnum::String(b)) => find(&a, &b),
|
(VDataEnum::String(a), VDataEnum::String(b)) => find(a, b),
|
||||||
(VDataEnum::String(a), VDataEnum::Reference(b)) => {
|
(VDataEnum::String(a), VDataEnum::Reference(b)) => match &b.data().0 {
|
||||||
match &b.lock().unwrap().data {
|
VDataEnum::String(b) => find(a, b),
|
||||||
VDataEnum::String(b) => find(&a, b),
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
},
|
||||||
}
|
(VDataEnum::Reference(a), VDataEnum::String(b)) => match &a.data().0 {
|
||||||
(VDataEnum::Reference(a), VDataEnum::String(b)) => {
|
VDataEnum::String(a) => find(a, b),
|
||||||
match &a.lock().unwrap().data {
|
|
||||||
VDataEnum::String(a) => find(a, &b),
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
},
|
||||||
}
|
|
||||||
(VDataEnum::Reference(a), VDataEnum::Reference(b)) => {
|
(VDataEnum::Reference(a), VDataEnum::Reference(b)) => {
|
||||||
if Arc::ptr_eq(&a, &b) {
|
if a.ptr_eq(b) {
|
||||||
// point to the same string
|
// point to the same string
|
||||||
// (this is required because a.lock() would cause b.lock() to wait indefinitely if you pass a two references to the same string here)
|
// (this is required because a.lock() would cause b.lock() to wait indefinitely if you pass a two references to the same string here)
|
||||||
VDataEnum::Int(0).to()
|
VDataEnum::Int(0).to()
|
||||||
} else {
|
} else {
|
||||||
match (&a.lock().unwrap().data, &b.lock().unwrap().data) {
|
match (&a.data().0, &b.data().0) {
|
||||||
(VDataEnum::String(a), VDataEnum::String(b)) => find(a, b),
|
(VDataEnum::String(a), VDataEnum::String(b)) => find(a, b),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
};
|
||||||
|
o
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Trim => {
|
Self::Trim => {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let VDataEnum::String(a) = args[0].run(vars, info).data {
|
if let VDataEnum::String(a) = &args[0].run(vars, info).data().0 {
|
||||||
VDataEnum::String(a.trim().to_string()).to()
|
VDataEnum::String(a.trim().to_string()).to()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@ -1667,18 +1785,18 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Substring => {
|
Self::Substring => {
|
||||||
if args.len() >= 2 {
|
if args.len() >= 2 {
|
||||||
if let VDataEnum::String(a) = args[0].run(vars, info).data {
|
if let VDataEnum::String(a) = &args[0].run(vars, info).data().0 {
|
||||||
if args.len() > 3 {
|
if args.len() > 3 {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
let left = if let VDataEnum::Int(left) = args[1].run(vars, info).data {
|
let left = if let VDataEnum::Int(left) = &args[1].run(vars, info).data().0 {
|
||||||
left
|
*left
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
let len = if args.len() == 3 {
|
let len = if args.len() == 3 {
|
||||||
if let VDataEnum::Int(len) = args[2].run(vars, info).data {
|
if let VDataEnum::Int(len) = &args[2].run(vars, info).data().0 {
|
||||||
Some(len)
|
Some(*len)
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
@ -1714,20 +1832,21 @@ impl BuiltinFunction {
|
|||||||
}
|
}
|
||||||
Self::Replace => {
|
Self::Replace => {
|
||||||
if let (VDataEnum::String(a), VDataEnum::String(b), VDataEnum::String(c)) = (
|
if let (VDataEnum::String(a), VDataEnum::String(b), VDataEnum::String(c)) = (
|
||||||
args[0].run(vars, info).data,
|
&args[0].run(vars, info).data().0,
|
||||||
args[1].run(vars, info).data,
|
&args[1].run(vars, info).data().0,
|
||||||
args[2].run(vars, info).data,
|
&args[2].run(vars, info).data().0,
|
||||||
) {
|
) {
|
||||||
VDataEnum::String(a.replace(&b, &c)).to()
|
VDataEnum::String(a.replace(b, c)).to()
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Regex => {
|
Self::Regex => {
|
||||||
if args.len() == 2 {
|
if args.len() == 2 {
|
||||||
if let (VDataEnum::String(a), VDataEnum::String(regex)) =
|
if let (VDataEnum::String(a), VDataEnum::String(regex)) = (
|
||||||
(args[0].run(vars, info).data, args[1].run(vars, info).data)
|
&args[0].run(vars, info).data().0,
|
||||||
{
|
&args[1].run(vars, info).data().0,
|
||||||
|
) {
|
||||||
match regex::Regex::new(regex.as_str()) {
|
match regex::Regex::new(regex.as_str()) {
|
||||||
Ok(regex) => VDataEnum::List(
|
Ok(regex) => VDataEnum::List(
|
||||||
VSingleType::String.to(),
|
VSingleType::String.to(),
|
||||||
@ -1757,9 +1876,9 @@ impl BuiltinFunction {
|
|||||||
fn vdata_to_bytes(vd: &Vec<VData>) -> Option<Vec<u8>> {
|
fn vdata_to_bytes(vd: &Vec<VData>) -> Option<Vec<u8>> {
|
||||||
let mut bytes = Vec::with_capacity(vd.len());
|
let mut bytes = Vec::with_capacity(vd.len());
|
||||||
for b in vd {
|
for b in vd {
|
||||||
if let VDataEnum::Int(b) = b.data {
|
if let VDataEnum::Int(b) = &b.data().0 {
|
||||||
bytes.push(if 0 <= b && b <= u8::MAX as isize {
|
bytes.push(if 0 <= *b && *b <= u8::MAX as isize {
|
||||||
b as u8
|
*b as u8
|
||||||
} else if b.is_negative() {
|
} else if b.is_negative() {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
|
@ -8,17 +8,12 @@ use super::{
|
|||||||
val_type::{VSingleType, VType},
|
val_type::{VSingleType, VType},
|
||||||
};
|
};
|
||||||
|
|
||||||
type Am<T> = Arc<Mutex<T>>;
|
|
||||||
fn am<T>(i: T) -> Am<T> {
|
|
||||||
Arc::new(Mutex::new(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct RBlock {
|
pub struct RBlock {
|
||||||
pub statements: Vec<RStatement>,
|
pub statements: Vec<RStatement>,
|
||||||
}
|
}
|
||||||
impl RBlock {
|
impl RBlock {
|
||||||
pub fn run(&self, vars: &Vec<Am<VData>>, info: &GSInfo) -> VData {
|
pub fn run(&self, vars: &mut Vec<VData>, info: &GSInfo) -> VData {
|
||||||
let mut last = None;
|
let mut last = None;
|
||||||
for statement in &self.statements {
|
for statement in &self.statements {
|
||||||
last = Some(statement.run(vars, info));
|
last = Some(statement.run(vars, info));
|
||||||
@ -48,7 +43,7 @@ pub struct RFunction {
|
|||||||
pub block: RBlock,
|
pub block: RBlock,
|
||||||
}
|
}
|
||||||
impl RFunction {
|
impl RFunction {
|
||||||
pub fn run(&self, vars: &Vec<Am<VData>>, info: &GSInfo) -> VData {
|
pub fn run(&self, vars: &mut Vec<VData>, info: &GSInfo) -> VData {
|
||||||
self.block.run(vars, info)
|
self.block.run(vars, info)
|
||||||
}
|
}
|
||||||
pub fn out(&self, input_types: &Vec<VSingleType>) -> VType {
|
pub fn out(&self, input_types: &Vec<VSingleType>) -> VType {
|
||||||
@ -91,19 +86,22 @@ pub struct RStatement {
|
|||||||
pub force_output_type: Option<VType>,
|
pub force_output_type: Option<VType>,
|
||||||
}
|
}
|
||||||
impl RStatement {
|
impl RStatement {
|
||||||
pub fn run(&self, vars: &Vec<Am<VData>>, info: &GSInfo) -> VData {
|
pub fn run(&self, vars: &mut Vec<VData>, info: &GSInfo) -> VData {
|
||||||
let out = self.statement.run(vars, info);
|
let out = self.statement.run(vars, info);
|
||||||
if let Some((v, derefs)) = self.output_to {
|
if let Some((v, derefs)) = self.output_to {
|
||||||
let mut val = vars[v].clone();
|
let mut val = dereference_n(&mut vars[v], derefs);
|
||||||
for _ in 0..derefs {
|
fn dereference_n(d: &mut VData, n: usize) -> VData {
|
||||||
let v = if let VDataEnum::Reference(v) = &val.lock().unwrap().data {
|
if n > 0 {
|
||||||
v.clone()
|
if let VDataEnum::Reference(v) = &mut d.data.lock().unwrap().0 {
|
||||||
|
dereference_n(v, n - 1)
|
||||||
} else {
|
} else {
|
||||||
unreachable!("dereferencing something that isn't a reference in assignment")
|
unreachable!("dereferencing something that isn't a reference in assignment")
|
||||||
};
|
|
||||||
val = v;
|
|
||||||
}
|
}
|
||||||
*val.lock().unwrap() = out;
|
} else {
|
||||||
|
d.clone_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val.assign(out.inner());
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
} else {
|
} else {
|
||||||
out
|
out
|
||||||
@ -142,7 +140,7 @@ pub enum RStatementEnum {
|
|||||||
EnumVariant(usize, RStatement),
|
EnumVariant(usize, RStatement),
|
||||||
}
|
}
|
||||||
impl RStatementEnum {
|
impl RStatementEnum {
|
||||||
pub fn run(&self, vars: &Vec<Am<VData>>, info: &GSInfo) -> VData {
|
pub fn run(&self, vars: &mut Vec<VData>, info: &GSInfo) -> VData {
|
||||||
match self {
|
match self {
|
||||||
Self::Value(v) => v.clone(),
|
Self::Value(v) => v.clone(),
|
||||||
Self::Tuple(v) => {
|
Self::Tuple(v) => {
|
||||||
@ -164,14 +162,16 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
Self::Variable(v, _, is_ref) => {
|
Self::Variable(v, _, is_ref) => {
|
||||||
if *is_ref {
|
if *is_ref {
|
||||||
VDataEnum::Reference(vars[*v].clone()).to()
|
// shared mutability (clone_mut)
|
||||||
|
VDataEnum::Reference(vars[*v].clone_mut()).to()
|
||||||
} else {
|
} else {
|
||||||
vars[*v].lock().unwrap().clone()
|
// Copy on Write (clone)
|
||||||
|
vars[*v].clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::FunctionCall(func, args) => {
|
Self::FunctionCall(func, args) => {
|
||||||
for (i, input) in func.inputs.iter().enumerate() {
|
for (i, input) in func.inputs.iter().enumerate() {
|
||||||
*vars[*input].lock().unwrap() = args[i].run(vars, info);
|
vars[*input] = args[i].run(vars, info);
|
||||||
}
|
}
|
||||||
func.run(vars, info)
|
func.run(vars, info)
|
||||||
}
|
}
|
||||||
@ -180,8 +180,8 @@ impl RStatementEnum {
|
|||||||
.run_fn(*fnid, args.iter().map(|arg| arg.run(vars, info)).collect()),
|
.run_fn(*fnid, args.iter().map(|arg| arg.run(vars, info)).collect()),
|
||||||
Self::Block(b) => b.run(vars, info),
|
Self::Block(b) => b.run(vars, info),
|
||||||
Self::If(c, t, e) => {
|
Self::If(c, t, e) => {
|
||||||
if let VDataEnum::Bool(v) = c.run(vars, info).data {
|
if let VDataEnum::Bool(v) = &c.run(vars, info).data().0 {
|
||||||
if v {
|
if *v {
|
||||||
t.run(vars, info)
|
t.run(vars, info)
|
||||||
} else {
|
} else {
|
||||||
if let Some(e) = e {
|
if let Some(e) = e {
|
||||||
@ -196,7 +196,7 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
Self::Loop(c) => loop {
|
Self::Loop(c) => loop {
|
||||||
// loops will break if the value matches.
|
// loops will break if the value matches.
|
||||||
if let Some(break_val) = c.run(vars, info).data.matches() {
|
if let Some(break_val) = c.run(vars, info).inner().matches() {
|
||||||
break break_val;
|
break break_val;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -204,17 +204,17 @@ impl RStatementEnum {
|
|||||||
// matching values also break with value from a for loop.
|
// matching values also break with value from a for loop.
|
||||||
let c = c.run(vars, info);
|
let c = c.run(vars, info);
|
||||||
let mut vars = vars.clone();
|
let mut vars = vars.clone();
|
||||||
let in_loop = |vars: &mut Vec<Arc<Mutex<VData>>>, c| {
|
let in_loop = |vars: &mut Vec<VData>, c| {
|
||||||
vars[*v] = Arc::new(Mutex::new(c));
|
vars[*v] = c;
|
||||||
b.run(&vars, info)
|
b.run(vars, info)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut oval = VDataEnum::Tuple(vec![]).to();
|
let mut oval = VDataEnum::Tuple(vec![]).to();
|
||||||
match c.data {
|
match &c.data().0 {
|
||||||
VDataEnum::Int(v) => {
|
VDataEnum::Int(v) => {
|
||||||
for i in 0..v {
|
for i in 0..*v {
|
||||||
if let Some(v) =
|
if let Some(v) =
|
||||||
in_loop(&mut vars, VDataEnum::Int(i).to()).data.matches()
|
in_loop(&mut vars, VDataEnum::Int(i).to()).inner().matches()
|
||||||
{
|
{
|
||||||
oval = v;
|
oval = v;
|
||||||
break;
|
break;
|
||||||
@ -225,7 +225,7 @@ impl RStatementEnum {
|
|||||||
for ch in v.chars() {
|
for ch in v.chars() {
|
||||||
if let Some(v) =
|
if let Some(v) =
|
||||||
in_loop(&mut vars, VDataEnum::String(ch.to_string()).to())
|
in_loop(&mut vars, VDataEnum::String(ch.to_string()).to())
|
||||||
.data
|
.inner()
|
||||||
.matches()
|
.matches()
|
||||||
{
|
{
|
||||||
oval = v;
|
oval = v;
|
||||||
@ -235,15 +235,15 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
VDataEnum::Tuple(v) | VDataEnum::List(_, v) => {
|
VDataEnum::Tuple(v) | VDataEnum::List(_, v) => {
|
||||||
for v in v {
|
for v in v {
|
||||||
if let Some(v) = in_loop(&mut vars, v).data.matches() {
|
if let Some(v) = in_loop(&mut vars, v.clone()).inner().matches() {
|
||||||
oval = v;
|
oval = v;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VDataEnum::Function(f) => loop {
|
VDataEnum::Function(f) => loop {
|
||||||
if let Some(v) = f.run(&vars, info).data.matches() {
|
if let Some(v) = f.run(&mut vars, info).inner().matches() {
|
||||||
if let Some(v) = in_loop(&mut vars, v).data.matches() {
|
if let Some(v) = in_loop(&mut vars, v).inner().matches() {
|
||||||
oval = v;
|
oval = v;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -270,10 +270,10 @@ impl RStatementEnum {
|
|||||||
Self::Match(match_on, cases) => 'm: {
|
Self::Match(match_on, cases) => 'm: {
|
||||||
for (case_condition, case_action) in cases {
|
for (case_condition, case_action) in cases {
|
||||||
// [t] => Some(t), t => Some(t), [] | false => None
|
// [t] => Some(t), t => Some(t), [] | false => None
|
||||||
if let Some(v) = case_condition.run(vars, info).data.matches() {
|
if let Some(v) = case_condition.run(vars, info).inner().matches() {
|
||||||
let og = { std::mem::replace(&mut *vars[*match_on].lock().unwrap(), v) };
|
let og = { std::mem::replace(&mut vars[*match_on], v) };
|
||||||
let res = case_action.run(vars, info);
|
let res = case_action.run(vars, info);
|
||||||
*vars[*match_on].lock().unwrap() = og;
|
vars[*match_on] = og;
|
||||||
break 'm res;
|
break 'm res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -377,17 +377,19 @@ impl RScript {
|
|||||||
}
|
}
|
||||||
pub fn run(&self, args: Vec<String>) -> VData {
|
pub fn run(&self, args: Vec<String>) -> VData {
|
||||||
let mut vars = Vec::with_capacity(self.info.vars);
|
let mut vars = Vec::with_capacity(self.info.vars);
|
||||||
vars.push(am(VDataEnum::List(
|
vars.push(
|
||||||
|
VDataEnum::List(
|
||||||
VSingleType::String.into(),
|
VSingleType::String.into(),
|
||||||
args.into_iter()
|
args.into_iter()
|
||||||
.map(|v| VDataEnum::String(v).to())
|
.map(|v| VDataEnum::String(v).to())
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
.to()));
|
.to(),
|
||||||
|
);
|
||||||
for _i in 1..self.info.vars {
|
for _i in 1..self.info.vars {
|
||||||
vars.push(am(VDataEnum::Tuple(vec![]).to()));
|
vars.push(VDataEnum::Tuple(vec![]).to());
|
||||||
}
|
}
|
||||||
self.main.run(&vars, &self.info)
|
self.main.run(&mut vars, &self.info)
|
||||||
}
|
}
|
||||||
pub fn info(&self) -> &GSInfo {
|
pub fn info(&self) -> &GSInfo {
|
||||||
&self.info
|
&self.info
|
||||||
|
@ -75,7 +75,7 @@ impl ToRunnableError {
|
|||||||
Self::CannotDereferenceTypeNTimes(og_type, derefs_wanted, last_valid_type) => {
|
Self::CannotDereferenceTypeNTimes(og_type, derefs_wanted, last_valid_type) => {
|
||||||
write!(f, "Cannot dereference type ")?;
|
write!(f, "Cannot dereference type ")?;
|
||||||
og_type.fmtgs(f, info)?;
|
og_type.fmtgs(f, info)?;
|
||||||
write!(f, "{derefs_wanted} times (stopped at ")?;
|
write!(f, " {derefs_wanted} times (stopped at ")?;
|
||||||
last_valid_type.fmtgs(f, info);
|
last_valid_type.fmtgs(f, info);
|
||||||
write!(f, ")")?;
|
write!(f, ")")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -5,16 +5,101 @@ use std::{
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
code_runnable::RFunction,
|
code_runnable::RFunction,
|
||||||
global_info::{GlobalScriptInfo, GSInfo},
|
global_info::{GSInfo, GlobalScriptInfo},
|
||||||
val_type::{VSingleType, VType},
|
val_type::{VSingleType, VType},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
|
||||||
pub struct VData {
|
pub struct VData {
|
||||||
pub data: VDataEnum,
|
/// (_, mutable) - if false, behave as CopyOnWrite.
|
||||||
|
pub data: Arc<Mutex<(VDataEnum, bool)>>,
|
||||||
|
}
|
||||||
|
impl VData {
|
||||||
|
/// if self is mutable, assigns the new value to the mutex.
|
||||||
|
/// if self is immutable, creates a new mutex and sets self to mutable.
|
||||||
|
pub fn assign(&mut self, new_val: VDataEnum) {
|
||||||
|
{
|
||||||
|
let mut d = self.data.lock().unwrap();
|
||||||
|
if d.1 {
|
||||||
|
d.0 = new_val;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*self = new_val.to();
|
||||||
|
}
|
||||||
|
pub fn inner_replace(&mut self, new_val: VDataEnum) -> VDataEnum {
|
||||||
|
{
|
||||||
|
let mut d = self.data.lock().unwrap();
|
||||||
|
if d.1 {
|
||||||
|
return std::mem::replace(&mut d.0, new_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let o = self.data().0.clone();
|
||||||
|
*self = new_val.to();
|
||||||
|
o
|
||||||
|
}
|
||||||
|
/// returns the contained VDataEnum. May or may not clone.
|
||||||
|
pub fn inner(self) -> VDataEnum {
|
||||||
|
self.data().0.clone()
|
||||||
|
}
|
||||||
|
/// ensures self is mutable, then returns a new instance of VData that is also mutable and uses the same Arc<Mutex<_>>.
|
||||||
|
pub fn clone_mut(&mut self) -> Self {
|
||||||
|
// if not mutable, copy and set to mutable.
|
||||||
|
self.make_mut();
|
||||||
|
// now, both self and the returned value are set to mutable and share the same mutex.
|
||||||
|
self.clone_mut_assume()
|
||||||
|
}
|
||||||
|
/// like clone_mut, but assumes self is already mutable, and therefor does not need to mutate self
|
||||||
|
/// as the Arc<Mutex<_>> will stay the same.
|
||||||
|
pub fn clone_mut_assume(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
data: Arc::clone(&self.data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn ptr_eq(&self, rhs: &Self) -> bool {
|
||||||
|
Arc::ptr_eq(&self.data, &rhs.data)
|
||||||
|
}
|
||||||
|
/// makes self mutable. might clone.
|
||||||
|
pub fn make_mut(&mut self) -> &mut Self {
|
||||||
|
{
|
||||||
|
let mut s = self.data.lock().unwrap();
|
||||||
|
if !s.1 {
|
||||||
|
*s = (s.0.clone(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn data(&self) -> std::sync::MutexGuard<(VDataEnum, bool)> {
|
||||||
|
self.data.lock().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Clone for VData {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
let mut d = self.data.lock().unwrap();
|
||||||
|
// set to immutable, locking the data as-is.
|
||||||
|
d.1 = false;
|
||||||
|
// then return the same arc (-> avoid cloning)
|
||||||
|
Self {
|
||||||
|
data: Arc::clone(&self.data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Debug for VData {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
let d = self.data.lock().unwrap();
|
||||||
|
if d.1 {
|
||||||
|
write!(f, "(!mutable!):{:?}", d.0)
|
||||||
|
} else {
|
||||||
|
write!(f, "(immutable):{:?}", d.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl PartialEq for VData {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.data().0 == other.data().0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Debug)]
|
||||||
pub enum VDataEnum {
|
pub enum VDataEnum {
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Int(isize),
|
Int(isize),
|
||||||
@ -24,15 +109,34 @@ pub enum VDataEnum {
|
|||||||
List(VType, Vec<VData>),
|
List(VType, Vec<VData>),
|
||||||
Function(RFunction),
|
Function(RFunction),
|
||||||
Thread(thread::VDataThread, VType),
|
Thread(thread::VDataThread, VType),
|
||||||
Reference(Arc<Mutex<VData>>),
|
Reference(VData),
|
||||||
EnumVariant(usize, Box<VData>),
|
EnumVariant(usize, Box<VData>),
|
||||||
}
|
}
|
||||||
|
impl Clone for VDataEnum {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
// exception: don't clone the value AND don't use CoW,
|
||||||
|
// because we want to share the same Arc<Mutex<_>>.
|
||||||
|
Self::Reference(r) => Self::Reference(r.clone_mut_assume()),
|
||||||
|
// default impls
|
||||||
|
Self::Bool(b) => Self::Bool(*b),
|
||||||
|
Self::Int(i) => Self::Int(*i),
|
||||||
|
Self::Float(f) => Self::Float(*f),
|
||||||
|
Self::String(s) => Self::String(s.clone()),
|
||||||
|
Self::Tuple(v) => Self::Tuple(v.clone()),
|
||||||
|
Self::List(t, v) => Self::List(t.clone(), v.clone()),
|
||||||
|
Self::Function(f) => Self::Function(f.clone()),
|
||||||
|
Self::Thread(th, ty) => Self::Thread(th.clone(), ty.clone()),
|
||||||
|
Self::EnumVariant(v, d) => Self::EnumVariant(v.clone(), d.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl PartialEq for VDataEnum {
|
impl PartialEq for VDataEnum {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Self::Reference(a), Self::Reference(b)) => *a.lock().unwrap() == *b.lock().unwrap(),
|
(Self::Reference(a), Self::Reference(b)) => a == b,
|
||||||
(Self::Reference(a), b) => a.lock().unwrap().data == *b,
|
(Self::Reference(a), b) => &a.data().0 == b,
|
||||||
(a, Self::Reference(b)) => *a == b.lock().unwrap().data,
|
(a, Self::Reference(b)) => a == &b.data().0,
|
||||||
(Self::Bool(a), Self::Bool(b)) => *a == *b,
|
(Self::Bool(a), Self::Bool(b)) => *a == *b,
|
||||||
(Self::Int(a), Self::Int(b)) => *a == *b,
|
(Self::Int(a), Self::Int(b)) => *a == *b,
|
||||||
(Self::Float(a), Self::Float(b)) => *a == *b,
|
(Self::Float(a), Self::Float(b)) => *a == *b,
|
||||||
@ -48,7 +152,7 @@ impl PartialEq for VDataEnum {
|
|||||||
|
|
||||||
impl VData {
|
impl VData {
|
||||||
pub fn safe_to_share(&self) -> bool {
|
pub fn safe_to_share(&self) -> bool {
|
||||||
self.data.safe_to_share()
|
self.data().0.safe_to_share()
|
||||||
}
|
}
|
||||||
pub fn out(&self) -> VType {
|
pub fn out(&self) -> VType {
|
||||||
VType {
|
VType {
|
||||||
@ -56,7 +160,7 @@ impl VData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn out_single(&self) -> VSingleType {
|
pub fn out_single(&self) -> VSingleType {
|
||||||
match &self.data {
|
match &self.data().0 {
|
||||||
VDataEnum::Bool(..) => VSingleType::Bool,
|
VDataEnum::Bool(..) => VSingleType::Bool,
|
||||||
VDataEnum::Int(..) => VSingleType::Int,
|
VDataEnum::Int(..) => VSingleType::Int,
|
||||||
VDataEnum::Float(..) => VSingleType::Float,
|
VDataEnum::Float(..) => VSingleType::Float,
|
||||||
@ -65,21 +169,23 @@ impl VData {
|
|||||||
VDataEnum::List(t, _) => VSingleType::List(t.clone()),
|
VDataEnum::List(t, _) => VSingleType::List(t.clone()),
|
||||||
VDataEnum::Function(f) => VSingleType::Function(f.input_output_map.clone()),
|
VDataEnum::Function(f) => VSingleType::Function(f.input_output_map.clone()),
|
||||||
VDataEnum::Thread(_, o) => VSingleType::Thread(o.clone()),
|
VDataEnum::Thread(_, o) => VSingleType::Thread(o.clone()),
|
||||||
VDataEnum::Reference(r) => r.lock().unwrap().out_single(),
|
VDataEnum::Reference(r) => VSingleType::Reference(Box::new(r.out_single())),
|
||||||
VDataEnum::EnumVariant(e, v) => VSingleType::EnumVariant(*e, v.out()),
|
VDataEnum::EnumVariant(e, v) => VSingleType::EnumVariant(*e, v.out()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn get(&self, i: usize) -> Option<Self> {
|
pub fn get(&self, i: usize) -> Option<Self> {
|
||||||
self.data.get(i)
|
self.data().0.get(i)
|
||||||
}
|
}
|
||||||
pub fn noenum(self) -> Self {
|
pub fn noenum(self) -> Self {
|
||||||
self.data.noenum()
|
self.inner().noenum()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VDataEnum {
|
impl VDataEnum {
|
||||||
pub fn to(self) -> VData {
|
pub fn to(self) -> VData {
|
||||||
VData { data: self }
|
VData {
|
||||||
|
data: Arc::new(Mutex::new((self, true))),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +219,7 @@ impl VDataEnum {
|
|||||||
None => None,
|
None => None,
|
||||||
},
|
},
|
||||||
Self::Tuple(v) | Self::List(_, v) => v.get(i).cloned(),
|
Self::Tuple(v) | Self::List(_, v) => v.get(i).cloned(),
|
||||||
Self::Reference(r) => r.lock().unwrap().get(i),
|
Self::Reference(r) => r.get(i),
|
||||||
Self::EnumVariant(_, v) => v.get(i),
|
Self::EnumVariant(_, v) => v.get(i),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -286,13 +392,17 @@ impl VDataEnum {
|
|||||||
Self::Thread(..) => write!(f, "[TODO] THREAD"),
|
Self::Thread(..) => write!(f, "[TODO] THREAD"),
|
||||||
Self::Reference(inner) => {
|
Self::Reference(inner) => {
|
||||||
write!(f, "&")?;
|
write!(f, "&")?;
|
||||||
inner.lock().unwrap().fmtgs(f, info)
|
inner.fmtgs(f, info)
|
||||||
}
|
}
|
||||||
Self::EnumVariant(variant, inner) => {
|
Self::EnumVariant(variant, inner) => {
|
||||||
if let Some(name) = if let Some(info) = info {
|
if let Some(name) = if let Some(info) = info {
|
||||||
info.enum_variants
|
info.enum_variants.iter().find_map(|(name, id)| {
|
||||||
.iter()
|
if id == variant {
|
||||||
.find_map(|(name, id)| if id == variant { Some(name) } else { None })
|
Some(name)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
} {
|
} {
|
||||||
@ -313,7 +423,7 @@ impl Display for VDataEnum {
|
|||||||
|
|
||||||
impl VData {
|
impl VData {
|
||||||
pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result {
|
pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result {
|
||||||
self.data.fmtgs(f, info)
|
self.data().0.fmtgs(f, info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Display for VData {
|
impl Display for VData {
|
||||||
|
@ -14,7 +14,7 @@ pub fn run(tutor: &mut Tutor) {
|
|||||||
",
|
",
|
||||||
));
|
));
|
||||||
loop {
|
loop {
|
||||||
match tutor.let_user_make_change().run(vec![]).data {
|
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||||
VDataEnum::Bool(true) => break,
|
VDataEnum::Bool(true) => break,
|
||||||
other => {
|
other => {
|
||||||
tutor.set_status(format!(" - Returned {} instead of true.", other));
|
tutor.set_status(format!(" - Returned {} instead of true.", other));
|
||||||
|
@ -35,7 +35,7 @@ mul()
|
|||||||
",
|
",
|
||||||
));
|
));
|
||||||
loop {
|
loop {
|
||||||
match tutor.let_user_make_change().run(vec![]).data {
|
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||||
VDataEnum::Int(160) => break,
|
VDataEnum::Int(160) => break,
|
||||||
other => {
|
other => {
|
||||||
tutor.set_status(format!(" - Returned {other} instead of 160"));
|
tutor.set_status(format!(" - Returned {other} instead of 160"));
|
||||||
|
@ -27,7 +27,7 @@ fn compute_sum(a int b int) {
|
|||||||
",
|
",
|
||||||
));
|
));
|
||||||
loop {
|
loop {
|
||||||
match tutor.let_user_make_change().run(vec![]).data {
|
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||||
VDataEnum::Int(15) => break,
|
VDataEnum::Int(15) => break,
|
||||||
other => {
|
other => {
|
||||||
tutor.set_status(format!(" - Returned {} instead of 15.", other));
|
tutor.set_status(format!(" - Returned {} instead of 15.", other));
|
||||||
|
@ -54,7 +54,7 @@ switch! words_in_string {}
|
|||||||
true
|
true
|
||||||
"));
|
"));
|
||||||
loop {
|
loop {
|
||||||
match tutor.let_user_make_change().run(vec![]).data {
|
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||||
VDataEnum::Tuple(v) if v.is_empty() => {
|
VDataEnum::Tuple(v) if v.is_empty() => {
|
||||||
tutor.set_status(format!(" - Returned an empty tuple."));
|
tutor.set_status(format!(" - Returned an empty tuple."));
|
||||||
tutor.update(None);
|
tutor.update(None);
|
||||||
|
@ -24,7 +24,7 @@ pub fn run(tutor: &mut Tutor) {
|
|||||||
// return any enum to return to the menu.
|
// return any enum to return to the menu.
|
||||||
"));
|
"));
|
||||||
loop {
|
loop {
|
||||||
match tutor.let_user_make_change().run(vec![]).data {
|
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||||
VDataEnum::EnumVariant(..) => break,
|
VDataEnum::EnumVariant(..) => break,
|
||||||
other => {
|
other => {
|
||||||
tutor.set_status(format!(" - Returned {other} instead of an enum."));
|
tutor.set_status(format!(" - Returned {other} instead of an enum."));
|
||||||
|
@ -18,9 +18,9 @@ five_less = sub(my_first_variable 5) // 10
|
|||||||
",
|
",
|
||||||
));
|
));
|
||||||
loop {
|
loop {
|
||||||
match tutor.let_user_make_change().run(vec![]).data {
|
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||||
VDataEnum::String(name) if !name.is_empty() => {
|
VDataEnum::String(name) if !name.is_empty() => {
|
||||||
tutor.i_name = Some(name);
|
tutor.i_name = Some(name.to_owned());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
VDataEnum::String(_) => {
|
VDataEnum::String(_) => {
|
||||||
|
@ -44,7 +44,7 @@ switch! first {
|
|||||||
list.get(8)
|
list.get(8)
|
||||||
"));
|
"));
|
||||||
loop {
|
loop {
|
||||||
match tutor.let_user_make_change().run(vec![]).data {
|
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||||
VDataEnum::Tuple(v) if !v.is_empty() => {
|
VDataEnum::Tuple(v) if !v.is_empty() => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,9 @@ go_to()
|
|||||||
",
|
",
|
||||||
));
|
));
|
||||||
loop {
|
loop {
|
||||||
match tutor.let_user_make_change().run(vec![]).data {
|
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||||
VDataEnum::Int(pos) if pos != 0 => {
|
VDataEnum::Int(pos) if *pos != 0 => {
|
||||||
tutor.current_pos = (pos.max(0) as usize).min(MAX_POS);
|
tutor.current_pos = ((*pos).max(0) as usize).min(MAX_POS);
|
||||||
match tutor.current_pos {
|
match tutor.current_pos {
|
||||||
0 => continue,
|
0 => continue,
|
||||||
1 => super::base_comments::run(&mut tutor),
|
1 => super::base_comments::run(&mut tutor),
|
||||||
|
@ -45,7 +45,7 @@ false
|
|||||||
i_name: None,
|
i_name: None,
|
||||||
};
|
};
|
||||||
loop {
|
loop {
|
||||||
if let VDataEnum::Bool(true) = tutor.let_user_make_change().run(vec![]).data {
|
if let VDataEnum::Bool(true) = &tutor.let_user_make_change().run(vec![]).data().0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ fn run_all() {
|
|||||||
let mut file = File::new(fs::read_to_string(file.path()).unwrap(), file.path());
|
let mut file = File::new(fs::read_to_string(file.path()).unwrap(), file.path());
|
||||||
// has to return true, otherwise the test will fail
|
// has to return true, otherwise the test will fail
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
parse::parse(&mut file).unwrap().run(vec![]).data,
|
parse::parse(&mut file).unwrap().run(vec![]).data().0,
|
||||||
VDataEnum::Bool(true)
|
VDataEnum::Bool(true)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -57,8 +57,11 @@ fn main() {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.1;
|
.1;
|
||||||
my_lib.callbacks.run_function.consuming = Some(Box::new(move |msg| {
|
my_lib.callbacks.run_function.consuming = Some(Box::new(move |msg| {
|
||||||
if let VDataEnum::String(url) = &msg.msg.args[0].data {
|
let url = if let VDataEnum::String(url) = &msg.msg.args[0].data().0 {
|
||||||
let url = url.clone();
|
url.clone()
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
let r = match reqwest::blocking::get(url) {
|
let r = match reqwest::blocking::get(url) {
|
||||||
Ok(response) => match response.text() {
|
Ok(response) => match response.text() {
|
||||||
@ -89,9 +92,6 @@ fn main() {
|
|||||||
};
|
};
|
||||||
msg.respond(r)
|
msg.respond(r)
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
// because we handle all callbacks, this never returns Err(unhandeled message).
|
// because we handle all callbacks, this never returns Err(unhandeled message).
|
||||||
// it returns Ok(()) if mers exits (i/o error in stdin/stdout), so we also exit if that happens.
|
// it returns Ok(()) if mers exits (i/o error in stdin/stdout), so we also exit if that happens.
|
||||||
|
Loading…
Reference in New Issue
Block a user